SAP 结构转JSON
*使用方式
jsonstr = zui2_json=>serialize( data = ls_in compress = abap_true pretty_name = zui2_json=>pretty_mode-camel_case ). "结构转成json
*&---------------------------------------------------------------------*
*& Include ZBC_UI2_JSON_CLS
*&---------------------------------------------------------------------* DEFINE escape_json_inplace.
* replace all occurrences of regex `[\\"]` in &1 with `\\$0`. <-- this is slower than 2 plain replaces
replace all occurrences of `\` in &1 with `\\`.
replace all occurrences of `"` in &1 with `\"`.
END-OF-DEFINITION. DEFINE escape_json.
move &1 to &2.
escape_json_inplace &2.
END-OF-DEFINITION. DEFINE dump_type. case &2->type_kind.
when cl_abap_typedescr=>typekind_float or cl_abap_typedescr=>typekind_int or cl_abap_typedescr=>typekind_int1 or
cl_abap_typedescr=>typekind_int2 or cl_abap_typedescr=>typekind_packed or `8`. " TYPEKIND_INT8 -> '8' only from 7.40.
if &2->type_kind eq cl_abap_typedescr=>typekind_packed and mv_ts_as_iso8601 eq c_bool-true and &2->absolute_name cp `\TYPE=TIMESTAMP*`.
if &1 is initial.
&3 = `""`.
else.
move &1 to &3.
if &2->absolute_name eq `\TYPE=TIMESTAMP`.
concatenate `"` &3(4) `-` &3+4(2) `-` &3+6(2) `T` &3+8(2) `:` &3+10(2) `:` &3+12(2) `.0000000Z"` into &3.
elseif &2->absolute_name eq `\TYPE=TIMESTAMPL`.
concatenate `"` &3(4) `-` &3+4(2) `-` &3+6(2) `T` &3+8(2) `:` &3+10(2) `:` &3+12(2) `.` &3+15(7) `Z"` into &3.
endif.
endif.
elseif &1 is initial.
&3 = `0`.
else.
move &1 to &3.
if &1 lt 0.
if &2->type_kind <> cl_abap_typedescr=>typekind_float. "float: sign is already at the beginning
shift &3 right circular.
endif.
else.
condense &3.
endif.
endif.
when cl_abap_typedescr=>typekind_num.
if mv_numc_as_string eq abap_true.
if &1 is initial.
&3 = `""`.
else.
concatenate `"` &1 `"` into &3.
endif.
else.
if &1 is initial.
&3 = `0`.
else.
move &1 to &3.
shift &3 left deleting leading ` 0`.
endif.
endif.
when cl_abap_typedescr=>typekind_string or cl_abap_typedescr=>typekind_csequence or cl_abap_typedescr=>typekind_clike.
if &1 is initial.
&3 = `""`.
elseif &2->absolute_name eq mc_json_type.
&3 = &1.
else.
escape_json &1 &3.
concatenate `"` &3 `"` into &3.
endif.
when cl_abap_typedescr=>typekind_xstring or cl_abap_typedescr=>typekind_hex.
if &1 is initial.
&3 = `""`.
else.
&3 = xstring_to_string( &1 ).
escape_json_inplace &3.
concatenate `"` &3 `"` into &3.
endif.
when cl_abap_typedescr=>typekind_char.
if &2->output_length eq 1 and mc_bool_types cs &2->absolute_name.
if &1 eq c_bool-true.
&3 = `true`. "#EC NOTEXT
elseif mc_bool_3state cs &2->absolute_name and &1 is initial.
&3 = `null`. "#EC NOTEXT
else.
&3 = `false`. "#EC NOTEXT
endif.
else.
escape_json &1 &3.
concatenate `"` &3 `"` into &3.
endif.
when cl_abap_typedescr=>typekind_date.
concatenate `"` &1(4) `-` &1+4(2) `-` &1+6(2) `"` into &3.
when cl_abap_typedescr=>typekind_time.
concatenate `"` &1(2) `:` &1+2(2) `:` &1+4(2) `"` into &3.
when others.
if &1 is initial.
&3 = `null`. "#EC NOTEXT
else.
move &1 to &3.
endif.
endcase. END-OF-DEFINITION. DEFINE format_name.
case &2.
when pretty_mode-camel_case.
&3 = pretty_name( &1 ).
when pretty_mode-extended.
&3 = pretty_name_ex( &1 ).
when pretty_mode-low_case.
&3 = &1.
translate &3 to lower case. "#EC SYNTCHAR
when others.
&3 = &1.
endcase.
END-OF-DEFINITION. DEFINE throw_error.
raise exception type cx_sy_move_cast_error.
END-OF-DEFINITION. DEFINE while_offset_cs.
* >= 7.02 alternative
* pos = find_any_not_of( val = json sub = &1 off = offset ).
* if pos eq -1. offset = length.
* else. offset = pos. endif. * < 7.02
while offset < length.
find first occurrence of json+offset(1) in &1.
if sy-subrc is not initial.
exit.
endif.
offset = offset + 1.
endwhile.
* < 7.02 END-OF-DEFINITION. DEFINE eat_white.
while_offset_cs sv_white_space.
END-OF-DEFINITION. DEFINE eat_string.
if json+offset(1) eq `"`.
mark = offset + 1.
offset = mark.
unescape = abap_false.
do.
find first occurrence of `"` in section offset offset of json match offset pos.
if sy-subrc is not initial.
throw_error.
endif.
offset = pos.
pos = pos - 1.
" if escaped search further
while pos ge 0 and json+pos(1) eq `\`.
pos = pos - 1.
unescape = abap_true.
endwhile.
match = ( offset - pos ) mod 2.
if match ne 0.
exit.
endif.
offset = offset + 1.
enddo.
match = offset - mark.
&1 = json+mark(match).
if unescape eq abap_true.
replace all occurrences of `\"` in &1 with `"`.
endif.
" \ shall be unescaped always, while we do not have check for that
replace all occurrences of `\\` in &1 with `\`.
offset = offset + 1.
else.
throw_error.
endif.
END-OF-DEFINITION. DEFINE eat_number.
mark = offset.
while_offset_cs `0123456789+-eE.`. "#EC NOTEXT
match = offset - mark.
&1 = json+mark(match).
END-OF-DEFINITION. DEFINE eat_bool.
mark = offset.
while_offset_cs `aeflnrstu`. "#EC NOTEXT
match = offset - mark.
if json+mark(match) eq `true`. "#EC NOTEXT
&1 = c_bool-true.
elseif json+mark(match) eq `false`. "#EC NOTEXT
if type_descr is bound and mc_bool_3state cs type_descr->absolute_name.
&1 = c_tribool-false.
else.
&1 = c_bool-false.
endif.
elseif json+mark(match) eq `null`. "#EC NOTEXT
clear &1.
endif.
END-OF-DEFINITION. DEFINE eat_char.
if offset < length and json+offset(1) eq &1.
offset = offset + 1.
else.
throw_error.
endif.
END-OF-DEFINITION.
*----------------------------------------------------------------------*
* CLASS ZUI2_JSON DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
class ZUI2_JSON definition. public section.
type-pools ABAP .
class CX_SY_CONVERSION_ERROR definition load . types JSON type STRING .
types BOOL type CHAR1 .
types TRIBOOL type CHAR1 .
types PRETTY_NAME_MODE type CHAR1 . constants:
BEGIN OF pretty_mode,
none TYPE char1 VALUE ``,
low_case TYPE char1 VALUE `L`,
camel_case TYPE char1 VALUE `X`,
extended TYPE char1 VALUE `Y`,
END OF pretty_mode .
constants:
BEGIN OF c_bool,
true TYPE bool VALUE `X`,
false TYPE bool VALUE ``,
END OF c_bool .
constants:
BEGIN OF c_tribool,
true TYPE tribool VALUE c_bool-true,
false TYPE tribool VALUE `-`,
undefined TYPE tribool VALUE ``,
END OF c_tribool .
class-data SV_WHITE_SPACE type STRING read-only .
constants MC_KEY_SEPARATOR type STRING value `-` .
class-data MC_BOOL_TYPES type STRING read-only value `\TYPE-POOL=ABAP\TYPE=ABAP_BOOL\TYPE=BOOLEAN\TYPE=BOOLE_D\TYPE=XFELD` .
class-data MC_BOOL_3STATE type STRING read-only value `\TYPE=BOOLEAN` .
constants VERSION type I value 4 .
class-data MC_JSON_TYPE type STRING read-only . class-methods CLASS_CONSTRUCTOR .
class-methods STRING_TO_XSTRING
importing
!IN type STRING
changing
value(OUT) type ANY .
class-methods XSTRING_TO_STRING
importing
!IN type ANY
returning
value(OUT) type STRING .
class-methods RAW_TO_STRING
importing
!IV_XSTRING type XSTRING
!IV_ENCODING type ABAP_ENCODING optional
returning
value(RV_STRING) type STRING .
class-methods STRING_TO_RAW
importing
!IV_STRING type STRING
!IV_ENCODING type ABAP_ENCODING optional
returning
value(RV_XSTRING) type XSTRING .
class-methods DUMP
importing
!DATA type DATA
!COMPRESS type BOOL default C_BOOL-FALSE
!TYPE_DESCR type ref to CL_ABAP_TYPEDESCR optional
!PRETTY_NAME type PRETTY_NAME_MODE default PRETTY_MODE-NONE
!ASSOC_ARRAYS type BOOL default C_BOOL-FALSE
!TS_AS_ISO8601 type BOOL default C_BOOL-FALSE
returning
value(R_JSON) type JSON .
class-methods DESERIALIZE
importing
!JSON type JSON optional
!JSONX type XSTRING optional
!PRETTY_NAME type PRETTY_NAME_MODE default PRETTY_MODE-NONE
!ASSOC_ARRAYS type BOOL default C_BOOL-FALSE
!ASSOC_ARRAYS_OPT type BOOL default C_BOOL-FALSE
changing
!DATA type DATA .
class-methods SERIALIZE
importing
!DATA type DATA
!COMPRESS type BOOL default C_BOOL-FALSE
!NAME type STRING optional
!PRETTY_NAME type PRETTY_NAME_MODE default PRETTY_MODE-NONE
!TYPE_DESCR type ref to CL_ABAP_TYPEDESCR optional
!ASSOC_ARRAYS type BOOL default C_BOOL-FALSE
!TS_AS_ISO8601 type BOOL default C_BOOL-FALSE
!EXPAND_INCLUDES type BOOL default C_BOOL-TRUE
!ASSOC_ARRAYS_OPT type BOOL default C_BOOL-FALSE
!NUMC_AS_STRING type BOOL default C_BOOL-FALSE
returning
value(R_JSON) type JSON .
class-methods GENERATE
importing
!JSON type JSON
!PRETTY_NAME type PRETTY_NAME_MODE default PRETTY_MODE-NONE
returning
value(RR_DATA) type ref to DATA .
methods DESERIALIZE_INT
importing
!JSON type JSON optional
!JSONX type XSTRING optional
changing
!DATA type DATA
raising
CX_SY_MOVE_CAST_ERROR .
methods GENERATE_INT
importing
!JSON type JSON
returning
value(RR_DATA) type ref to DATA .
methods SERIALIZE_INT
importing
!DATA type DATA
!NAME type STRING optional
!TYPE_DESCR type ref to CL_ABAP_TYPEDESCR optional
returning
value(R_JSON) type JSON .
methods CONSTRUCTOR
importing
!COMPRESS type BOOL default C_BOOL-FALSE
!PRETTY_NAME type PRETTY_NAME_MODE default PRETTY_MODE-NONE
!ASSOC_ARRAYS type BOOL default C_BOOL-FALSE
!TS_AS_ISO8601 type BOOL default C_BOOL-FALSE
!EXPAND_INCLUDES type BOOL default C_BOOL-TRUE
!ASSOC_ARRAYS_OPT type BOOL default C_BOOL-FALSE
!STRICT_MODE type BOOL default C_BOOL-FALSE
!NUMC_AS_STRING type BOOL default C_BOOL-FALSE .
class-methods BOOL_TO_TRIBOOL
importing
!IV_BOOL type BOOL
returning
value(RV_TRIBOOL) type TRIBOOL .
class-methods TRIBOOL_TO_BOOL
importing
!IV_TRIBOOL type TRIBOOL
returning
value(RV_BOOL) type BOOL .
protected section. types:
*"* protected components of class ZUI2_JSON
*"* do not include other source files here!!!
BEGIN OF pretty_name_pair,
in TYPE string,
out TYPE string,
END OF pretty_name_pair .
types:
BEGIN OF t_s_symbol,
header TYPE string,
name TYPE string,
type TYPE REF TO cl_abap_datadescr,
value TYPE REF TO data,
compressable TYPE abap_bool,
read_only TYPE abap_bool,
END OF t_s_symbol .
types:
t_t_symbol TYPE STANDARD TABLE OF t_s_symbol WITH DEFAULT KEY .
types:
BEGIN OF t_s_field_cache,
name TYPE string,
type TYPE REF TO cl_abap_datadescr,
value TYPE REF TO data,
END OF t_s_field_cache .
types:
t_t_field_cache TYPE HASHED TABLE OF t_s_field_cache WITH UNIQUE KEY name . data MV_COMPRESS type BOOL .
data MV_PRETTY_NAME type PRETTY_NAME_MODE .
data MV_ASSOC_ARRAYS type BOOL .
data MV_TS_AS_ISO8601 type BOOL .
data:
mt_cache_pretty TYPE HASHED TABLE OF pretty_name_pair WITH UNIQUE KEY in .
data MV_EXPAND_INCLUDES type BOOL .
data MV_ASSOC_ARRAYS_OPT type BOOL .
data MV_STRICT_MODE type BOOL .
data MV_NUMC_AS_STRING type BOOL . methods DUMP_SYMBOLS
final
importing
!IT_SYMBOLS type T_T_SYMBOL
returning
value(R_JSON) type JSON .
methods GET_SYMBOLS
final
importing
!TYPE_DESCR type ref to CL_ABAP_TYPEDESCR
!DATA type ref to DATA optional
!OBJECT type ref to OBJECT optional
!INCLUDE_ALIASES type ABAP_BOOL default ABAP_FALSE
returning
value(RESULT) type T_T_SYMBOL .
methods GET_FIELDS
final
importing
!TYPE_DESCR type ref to CL_ABAP_TYPEDESCR
!DATA type ref to DATA optional
!OBJECT type ref to OBJECT optional
returning
value(RT_FIELDS) type T_T_FIELD_CACHE .
methods DUMP_INT
final
importing
!DATA type DATA
!TYPE_DESCR type ref to CL_ABAP_TYPEDESCR optional
returning
value(R_JSON) type JSON .
methods IS_COMPRESSABLE
importing
!TYPE_DESCR type ref to CL_ABAP_TYPEDESCR
!NAME type CSEQUENCE
returning
value(RV_COMPRESS) type ABAP_BOOL .
methods RESTORE
final
importing
!JSON type JSON
!LENGTH type I
value(TYPE_DESCR) type ref to CL_ABAP_TYPEDESCR optional
!FIELD_CACHE type T_T_FIELD_CACHE optional
changing
!DATA type DATA optional
!OFFSET type I default 0
raising
CX_SY_MOVE_CAST_ERROR .
methods RESTORE_TYPE
final
importing
!JSON type JSON
!LENGTH type I
value(TYPE_DESCR) type ref to CL_ABAP_TYPEDESCR optional
!FIELD_CACHE type T_T_FIELD_CACHE optional
changing
!DATA type DATA optional
!OFFSET type I default 0
raising
CX_SY_MOVE_CAST_ERROR .
methods DUMP_TYPE
final
importing
!DATA type DATA
!TYPE_DESCR type ref to CL_ABAP_ELEMDESCR
returning
value(R_JSON) type JSON .
methods DUMP_TYPE_EX
importing
!DATA type DATA
returning
value(R_JSON) type JSON .
methods PRETTY_NAME_EX
importing
!IN type CSEQUENCE
returning
value(OUT) type STRING .
methods GENERATE_INT_EX
final
importing
!JSON type JSON
!LENGTH type I
changing
!DATA type DATA
!OFFSET type I .
methods PRETTY_NAME
importing
!IN type CSEQUENCE
returning
value(OUT) type STRING .
class-methods ESCAPE
importing
!IN type ANY
returning
value(OUT) type STRING .
PRIVATE SECTION.
*"* private components of class ZUI2_JSON
*"* do not include other source files here!!!
ENDCLASS. CLASS ZUI2_JSON IMPLEMENTATION. * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZUI2_JSON=>BOOL_TO_TRIBOOL
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_BOOL TYPE BOOL
* | [<-()] RV_TRIBOOL TYPE TRIBOOL
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD BOOL_TO_TRIBOOL.
IF iv_bool EQ c_bool-true.
rv_tribool = c_tribool-true.
ELSEIF iv_bool EQ abap_undefined. " fall back for abap _bool
rv_tribool = c_tribool-undefined.
ELSE.
rv_tribool = c_tribool-false.
ENDIF.
ENDMETHOD. "bool_to_tribool * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZUI2_JSON=>CLASS_CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD CLASS_CONSTRUCTOR. DATA: lo_bool_type_descr TYPE REF TO cl_abap_typedescr,
lo_tribool_type_descr TYPE REF TO cl_abap_typedescr,
lo_json_type_descr TYPE REF TO cl_abap_typedescr,
lv_json_string TYPE json. lo_bool_type_descr = cl_abap_typedescr=>describe_by_data( c_bool-true ).
lo_tribool_type_descr = cl_abap_typedescr=>describe_by_data( c_tribool-true ).
lo_json_type_descr = cl_abap_typedescr=>describe_by_data( lv_json_string ). CONCATENATE mc_bool_types lo_bool_type_descr->absolute_name lo_tribool_type_descr->absolute_name INTO mc_bool_types.
CONCATENATE mc_bool_3state lo_tribool_type_descr->absolute_name INTO mc_bool_3state.
CONCATENATE mc_json_type lo_json_type_descr->absolute_name INTO mc_json_type. sv_white_space = cl_abap_char_utilities=>get_simple_spaces_for_cur_cp( ). ENDMETHOD. "class_constructor * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZUI2_JSON->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] COMPRESS TYPE BOOL (default =C_BOOL-FALSE)
* | [--->] PRETTY_NAME TYPE PRETTY_NAME_MODE (default =PRETTY_MODE-NONE)
* | [--->] ASSOC_ARRAYS TYPE BOOL (default =C_BOOL-FALSE)
* | [--->] TS_AS_ISO8601 TYPE BOOL (default =C_BOOL-FALSE)
* | [--->] EXPAND_INCLUDES TYPE BOOL (default =C_BOOL-TRUE)
* | [--->] ASSOC_ARRAYS_OPT TYPE BOOL (default =C_BOOL-FALSE)
* | [--->] STRICT_MODE TYPE BOOL (default =C_BOOL-FALSE)
* | [--->] NUMC_AS_STRING TYPE BOOL (default =C_BOOL-FALSE)
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD CONSTRUCTOR.
mv_compress = compress.
mv_pretty_name = pretty_name.
mv_assoc_arrays = assoc_arrays.
mv_ts_as_iso8601 = ts_as_iso8601.
mv_expand_includes = expand_includes.
mv_assoc_arrays_opt = assoc_arrays_opt.
mv_strict_mode = strict_mode.
mv_numc_as_string = numc_as_string.
ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZUI2_JSON=>DESERIALIZE
* +-------------------------------------------------------------------------------------------------+
* | [--->] JSON TYPE JSON(optional)
* | [--->] JSONX TYPE XSTRING(optional)
* | [--->] PRETTY_NAME TYPE PRETTY_NAME_MODE (default =PRETTY_MODE-NONE)
* | [--->] ASSOC_ARRAYS TYPE BOOL (default =C_BOOL-FALSE)
* | [--->] ASSOC_ARRAYS_OPT TYPE BOOL (default =C_BOOL-FALSE)
* | [<-->] DATA TYPE DATA
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD DESERIALIZE. DATA: lo_json TYPE REF TO ZUI2_JSON. " **********************************************************************
"! Usage examples and documentation can be found on SCN:
" http://wiki.scn.sap.com/wiki/display/Snippets/One+more+ABAP+to+JSON+Serializer+and+Deserializer
" ********************************************************************** " IF json IS NOT INITIAL OR jsonx IS NOT INITIAL. CREATE OBJECT lo_json
EXPORTING
pretty_name = pretty_name
assoc_arrays = assoc_arrays
assoc_arrays_opt = assoc_arrays_opt. TRY .
lo_json->deserialize_int( EXPORTING json = json jsonx = jsonx CHANGING data = data ).
CATCH cx_sy_move_cast_error.
ENDTRY. ENDIF. ENDMETHOD. "deserialize * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZUI2_JSON->DESERIALIZE_INT
* +-------------------------------------------------------------------------------------------------+
* | [--->] JSON TYPE JSON(optional)
* | [--->] JSONX TYPE XSTRING(optional)
* | [<-->] DATA TYPE DATA
* | [!CX!] CX_SY_MOVE_CAST_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD DESERIALIZE_INT. DATA: length TYPE i,
unescaped LIKE json. " **********************************************************************
"! Usage examples and documentation can be found on SCN:
" http://wiki.scn.sap.com/wiki/display/Snippets/One+more+ABAP+to+JSON+Serializer+and+Deserializer
" ********************************************************************** " IF json IS NOT INITIAL OR jsonx IS NOT INITIAL. IF jsonx IS NOT INITIAL.
unescaped = raw_to_string( jsonx ).
ELSE.
unescaped = json.
ENDIF. " to eliminate numeric replacement calls for every single sting value, we do
" replacement over all JSON text, while this shall not destroy JSON structure
REPLACE ALL OCCURRENCES OF `\r\n` IN unescaped WITH cl_abap_char_utilities=>cr_lf.
REPLACE ALL OCCURRENCES OF `\n` IN unescaped WITH cl_abap_char_utilities=>newline.
REPLACE ALL OCCURRENCES OF `\t` IN unescaped WITH cl_abap_char_utilities=>horizontal_tab.
" REPLACE ALL OCCURRENCES OF `\f` IN r_json WITH cl_abap_char_utilities=>form_feed.
" REPLACE ALL OCCURRENCES OF `\b` IN r_json WITH cl_abap_char_utilities=>backspace. length = NUMOFCHAR( unescaped ).
restore_type( EXPORTING json = unescaped length = length CHANGING data = data ). ENDIF. ENDMETHOD. "deserialize * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZUI2_JSON=>DUMP
* +-------------------------------------------------------------------------------------------------+
* | [--->] DATA TYPE DATA
* | [--->] COMPRESS TYPE BOOL (default =C_BOOL-FALSE)
* | [--->] TYPE_DESCR TYPE REF TO CL_ABAP_TYPEDESCR(optional)
* | [--->] PRETTY_NAME TYPE PRETTY_NAME_MODE (default =PRETTY_MODE-NONE)
* | [--->] ASSOC_ARRAYS TYPE BOOL (default =C_BOOL-FALSE)
* | [--->] TS_AS_ISO8601 TYPE BOOL (default =C_BOOL-FALSE)
* | [<-()] R_JSON TYPE JSON
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD DUMP. DATA: lo_json TYPE REF TO ZUI2_JSON. CREATE OBJECT lo_json
EXPORTING
compress = compress
pretty_name = pretty_name
assoc_arrays = assoc_arrays
ts_as_iso8601 = ts_as_iso8601. r_json = lo_json->dump_int( data = data type_descr = type_descr ). ENDMETHOD. "dump * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZUI2_JSON->DUMP_INT
* +-------------------------------------------------------------------------------------------------+
* | [--->] DATA TYPE DATA
* | [--->] TYPE_DESCR TYPE REF TO CL_ABAP_TYPEDESCR(optional)
* | [<-()] R_JSON TYPE JSON
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD DUMP_INT. DATA: lo_typedesc TYPE REF TO cl_abap_typedescr,
lo_elem_descr TYPE REF TO cl_abap_elemdescr,
lo_classdesc TYPE REF TO cl_abap_classdescr,
lo_structdesc TYPE REF TO cl_abap_structdescr,
lo_tabledescr TYPE REF TO cl_abap_tabledescr,
lt_symbols TYPE t_t_symbol,
lt_keys LIKE lt_symbols,
lt_properties TYPE STANDARD TABLE OF string,
lt_fields TYPE STANDARD TABLE OF string,
lo_obj_ref TYPE REF TO object,
lo_data_ref TYPE REF TO data,
ls_skip_key TYPE LINE OF abap_keydescr_tab,
lv_array_opt TYPE abap_bool,
lv_prop_name TYPE string,
lv_keyval TYPE string,
lv_itemval TYPE string. FIELD-SYMBOLS: <line> TYPE ANY,
<value> TYPE ANY,
<data> TYPE data,
<key> TYPE LINE OF abap_keydescr_tab,
<symbol> LIKE LINE OF lt_symbols,
<table> TYPE ANY TABLE. " we need here macro instead of method calls because of the performance reasons.
" based on SAT measurements. CASE type_descr->kind.
WHEN cl_abap_typedescr=>kind_ref. IF data IS INITIAL.
r_json = `null`. "#EC NOTEXT
ELSEIF type_descr->type_kind EQ cl_abap_typedescr=>typekind_dref.
lo_data_ref ?= data.
lo_typedesc = cl_abap_typedescr=>describe_by_data_ref( lo_data_ref ).
ASSIGN lo_data_ref->* TO <data>.
r_json = dump_int( data = <data> type_descr = lo_typedesc ).
ELSE.
lo_obj_ref ?= data.
lo_classdesc ?= cl_abap_typedescr=>describe_by_object_ref( lo_obj_ref ).
lt_symbols = get_symbols( type_descr = lo_classdesc object = lo_obj_ref ).
r_json = dump_symbols( lt_symbols ).
ENDIF. WHEN cl_abap_typedescr=>kind_elem.
lo_elem_descr ?= type_descr.
"r_json = dump_type( data = data type_descr = lo_elem_descr ).
dump_type data lo_elem_descr r_json. WHEN cl_abap_typedescr=>kind_struct. lo_structdesc ?= type_descr.
GET REFERENCE OF data INTO lo_data_ref.
lt_symbols = get_symbols( type_descr = lo_structdesc data = lo_data_ref ).
r_json = dump_symbols( lt_symbols ). WHEN cl_abap_typedescr=>kind_table. lo_tabledescr ?= type_descr.
lo_typedesc = lo_tabledescr->get_table_line_type( ). ASSIGN data TO <table>. " optimization for structured tables
IF lo_typedesc->kind EQ cl_abap_typedescr=>kind_struct.
lo_structdesc ?= lo_typedesc.
CREATE DATA lo_data_ref LIKE LINE OF <table>.
ASSIGN lo_data_ref->* TO <line>.
lt_symbols = get_symbols( type_descr = lo_structdesc data = lo_data_ref ). " here we have differentiation of output of simple table to JSON array
" and sorted or hashed table with unique key into JSON associative array
IF lo_tabledescr->has_unique_key IS NOT INITIAL AND mv_assoc_arrays IS NOT INITIAL. IF lo_tabledescr->key_defkind EQ lo_tabledescr->keydefkind_user.
LOOP AT lo_tabledescr->key ASSIGNING <key>.
READ TABLE lt_symbols WITH KEY name = <key>-name ASSIGNING <symbol>.
APPEND <symbol> TO lt_keys.
ENDLOOP.
ENDIF. IF LINES( lo_tabledescr->key ) EQ 1.
READ TABLE lo_tabledescr->key INDEX 1 INTO ls_skip_key.
DELETE lt_symbols WHERE name EQ ls_skip_key-name.
" remove object wrapping for simple name-value tables
IF mv_assoc_arrays_opt EQ abap_true AND LINES( lt_symbols ) EQ 1.
lv_array_opt = abap_true.
ENDIF.
ENDIF. LOOP AT <table> INTO <line>.
CLEAR: lt_fields, lv_prop_name.
LOOP AT lt_symbols ASSIGNING <symbol>.
ASSIGN <symbol>-value->* TO <value>.
IF mv_compress IS INITIAL OR <value> IS NOT INITIAL OR <symbol>-compressable EQ abap_false.
IF <symbol>-type->kind EQ cl_abap_typedescr=>kind_elem.
lo_elem_descr ?= <symbol>-type.
"lv_itemval = dump_type( data = <value> type_descr = lo_elem_descr ).
dump_type <value> lo_elem_descr lv_itemval.
ELSE.
lv_itemval = dump_int( data = <value> type_descr = <symbol>-type ).
ENDIF.
IF lv_array_opt EQ abap_false.
CONCATENATE <symbol>-header lv_itemval INTO lv_itemval.
ENDIF.
APPEND lv_itemval TO lt_fields.
ENDIF.
ENDLOOP. IF lo_tabledescr->key_defkind EQ lo_tabledescr->keydefkind_user.
LOOP AT lt_keys ASSIGNING <symbol>.
ASSIGN <symbol>-value->* TO <value>.
MOVE <value> TO lv_keyval.
CONDENSE lv_keyval.
IF lv_prop_name IS NOT INITIAL.
CONCATENATE lv_prop_name mc_key_separator lv_keyval INTO lv_prop_name.
ELSE.
lv_prop_name = lv_keyval.
ENDIF.
ENDLOOP.
ELSE.
LOOP AT lt_symbols ASSIGNING <symbol>.
ASSIGN <symbol>-value->* TO <value>.
MOVE <value> TO lv_keyval.
CONDENSE lv_keyval.
IF lv_prop_name IS NOT INITIAL.
CONCATENATE lv_prop_name mc_key_separator lv_keyval INTO lv_prop_name.
ELSE.
lv_prop_name = lv_keyval.
ENDIF.
ENDLOOP.
ENDIF. CONCATENATE LINES OF lt_fields INTO lv_itemval SEPARATED BY `,`.
IF lv_array_opt EQ abap_false.
CONCATENATE `"` lv_prop_name `":{` lv_itemval `}` INTO lv_itemval.
ELSE.
CONCATENATE `"` lv_prop_name `":` lv_itemval `` INTO lv_itemval.
ENDIF.
APPEND lv_itemval TO lt_properties. ENDLOOP. CONCATENATE LINES OF lt_properties INTO r_json SEPARATED BY `,`.
CONCATENATE `{` r_json `}` INTO r_json. ELSE. LOOP AT <table> INTO <line>.
CLEAR lt_fields.
LOOP AT lt_symbols ASSIGNING <symbol>.
ASSIGN <symbol>-value->* TO <value>.
IF mv_compress IS INITIAL OR <value> IS NOT INITIAL OR <symbol>-compressable EQ abap_false.
IF <symbol>-type->kind EQ cl_abap_typedescr=>kind_elem.
lo_elem_descr ?= <symbol>-type.
"lv_itemval = dump_type( data = <value> type_descr = lo_elem_descr ).
dump_type <value> lo_elem_descr lv_itemval.
ELSE.
lv_itemval = dump_int( data = <value> type_descr = <symbol>-type ).
ENDIF.
CONCATENATE <symbol>-header lv_itemval INTO lv_itemval.
APPEND lv_itemval TO lt_fields.
ENDIF.
ENDLOOP. CONCATENATE LINES OF lt_fields INTO lv_itemval SEPARATED BY `,`.
CONCATENATE `{` lv_itemval `}` INTO lv_itemval.
APPEND lv_itemval TO lt_properties.
ENDLOOP. CONCATENATE LINES OF lt_properties INTO r_json SEPARATED BY `,`.
CONCATENATE `[` r_json `]` INTO r_json. ENDIF.
ELSE.
LOOP AT <table> ASSIGNING <value>.
lv_itemval = dump_int( data = <value> type_descr = lo_typedesc ).
APPEND lv_itemval TO lt_properties.
ENDLOOP. CONCATENATE LINES OF lt_properties INTO r_json SEPARATED BY `,`.
CONCATENATE `[` r_json `]` INTO r_json.
ENDIF. ENDCASE. ENDMETHOD. "dump * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZUI2_JSON->DUMP_SYMBOLS
* +-------------------------------------------------------------------------------------------------+
* | [--->] IT_SYMBOLS TYPE T_T_SYMBOL
* | [<-()] R_JSON TYPE JSON
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD DUMP_SYMBOLS. DATA: lv_properties TYPE STANDARD TABLE OF string,
lv_itemval TYPE string. FIELD-SYMBOLS: <value> TYPE ANY,
<symbol> LIKE LINE OF it_symbols. LOOP AT it_symbols ASSIGNING <symbol>.
ASSIGN <symbol>-value->* TO <value>.
IF mv_compress IS INITIAL OR <value> IS NOT INITIAL OR <symbol>-compressable EQ abap_false.
lv_itemval = dump_int( data = <value> type_descr = <symbol>-type ).
CONCATENATE <symbol>-header lv_itemval INTO lv_itemval.
APPEND lv_itemval TO lv_properties.
ENDIF.
ENDLOOP. CONCATENATE LINES OF lv_properties INTO r_json SEPARATED BY `,`.
CONCATENATE `{` r_json `}` INTO r_json. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZUI2_JSON->DUMP_TYPE
* +-------------------------------------------------------------------------------------------------+
* | [--->] DATA TYPE DATA
* | [--->] TYPE_DESCR TYPE REF TO CL_ABAP_ELEMDESCR
* | [<-()] R_JSON TYPE JSON
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD DUMP_TYPE. CASE type_descr->type_kind.
WHEN cl_abap_typedescr=>typekind_float OR cl_abap_typedescr=>typekind_int OR cl_abap_typedescr=>typekind_int1 OR
cl_abap_typedescr=>typekind_int2 OR cl_abap_typedescr=>typekind_packed OR `8`. " TYPEKIND_INT8 -> '8' only from 7.40 IF type_descr->type_kind EQ cl_abap_typedescr=>typekind_packed AND mv_ts_as_iso8601 EQ c_bool-true AND type_descr->absolute_name CP `\TYPE=TIMESTAMP*`.
IF data IS INITIAL.
r_json = `""`.
ELSE.
MOVE data TO r_json.
IF type_descr->absolute_name EQ `\TYPE=TIMESTAMP`.
CONCATENATE `"` r_json(4) `-` r_json+4(2) `-` r_json+6(2) `T` r_json+8(2) `:` r_json+10(2) `:` r_json+12(2) `.0000000Z"` INTO r_json.
ELSEIF type_descr->absolute_name EQ `\TYPE=TIMESTAMPL`.
CONCATENATE `"` r_json(4) `-` r_json+4(2) `-` r_json+6(2) `T` r_json+8(2) `:` r_json+10(2) `:` r_json+12(2) `.` r_json+15(7) `Z"` INTO r_json.
ENDIF.
ENDIF.
ELSEIF data IS INITIAL.
r_json = `0`.
ELSE.
MOVE data TO r_json.
IF data LT 0.
IF type_descr->type_kind <> cl_abap_typedescr=>typekind_float. "float: sign is already at the beginning
SHIFT r_json RIGHT CIRCULAR.
ENDIF.
ELSE.
CONDENSE r_json.
ENDIF.
ENDIF.
WHEN cl_abap_typedescr=>typekind_num.
IF mv_numc_as_string EQ abap_true.
IF data IS INITIAL.
r_json = `""`.
ELSE.
CONCATENATE `"` data `"` INTO r_json.
ENDIF.
ELSE.
IF data IS INITIAL.
r_json = `0`.
ELSE.
MOVE data TO r_json.
SHIFT r_json LEFT DELETING LEADING ` 0`.
ENDIF.
ENDIF.
WHEN cl_abap_typedescr=>typekind_string OR cl_abap_typedescr=>typekind_csequence OR cl_abap_typedescr=>typekind_clike.
IF data IS INITIAL.
r_json = `""`.
ELSEIF type_descr->absolute_name EQ mc_json_type.
r_json = data.
ELSE.
r_json = escape( data ).
CONCATENATE `"` r_json `"` INTO r_json.
ENDIF.
WHEN cl_abap_typedescr=>typekind_xstring OR cl_abap_typedescr=>typekind_hex.
IF data IS INITIAL.
r_json = `""`.
ELSE.
r_json = xstring_to_string( data ).
r_json = escape( r_json ).
CONCATENATE `"` r_json `"` INTO r_json.
ENDIF.
WHEN cl_abap_typedescr=>typekind_char.
IF type_descr->output_length EQ 1 AND mc_bool_types CS type_descr->absolute_name.
IF data EQ c_bool-true.
r_json = `true`. "#EC NOTEXT
ELSEIF mc_bool_3state CS type_descr->absolute_name AND data IS INITIAL.
r_json = `null`. "#EC NOTEXT
ELSE.
r_json = `false`. "#EC NOTEXT
ENDIF.
ELSE.
r_json = escape( data ).
CONCATENATE `"` r_json `"` INTO r_json.
ENDIF.
WHEN cl_abap_typedescr=>typekind_date.
CONCATENATE `"` data(4) `-` data+4(2) `-` data+6(2) `"` INTO r_json.
WHEN cl_abap_typedescr=>typekind_time.
CONCATENATE `"` data(2) `:` data+2(2) `:` data+4(2) `"` INTO r_json.
WHEN OTHERS.
IF data IS INITIAL.
r_json = `null`. "#EC NOTEXT
ELSE.
MOVE data TO r_json.
ENDIF.
ENDCASE. ENDMETHOD. "dump_type * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZUI2_JSON->DUMP_TYPE_EX
* +-------------------------------------------------------------------------------------------------+
* | [--->] DATA TYPE DATA
* | [<-()] R_JSON TYPE JSON
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD DUMP_TYPE_EX. DATA: lo_descr TYPE REF TO cl_abap_elemdescr.
lo_descr ?= cl_abap_typedescr=>describe_by_data( data ).
r_json = dump_type( data = data type_descr = lo_descr ). ENDMETHOD. "DUMP_TYPE_EX * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Protected Method ZUI2_JSON=>ESCAPE
* +-------------------------------------------------------------------------------------------------+
* | [--->] IN TYPE ANY
* | [<-()] OUT TYPE STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD ESCAPE. MOVE in TO out. REPLACE ALL OCCURRENCES OF `\` IN out WITH `\\`.
REPLACE ALL OCCURRENCES OF `"` IN out WITH `\"`. ENDMETHOD. "escape * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZUI2_JSON=>GENERATE
* +-------------------------------------------------------------------------------------------------+
* | [--->] JSON TYPE JSON
* | [--->] PRETTY_NAME TYPE PRETTY_NAME_MODE (default =PRETTY_MODE-NONE)
* | [<-()] RR_DATA TYPE REF TO DATA
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD GENERATE. DATA: lo_json TYPE REF TO ZUI2_JSON,
lv_json LIKE json. lv_json = json. REPLACE ALL OCCURRENCES OF `\r\n` IN lv_json WITH cl_abap_char_utilities=>cr_lf.
REPLACE ALL OCCURRENCES OF `\n` IN lv_json WITH cl_abap_char_utilities=>newline.
REPLACE ALL OCCURRENCES OF `\t` IN lv_json WITH cl_abap_char_utilities=>horizontal_tab. CREATE OBJECT lo_json
EXPORTING
pretty_name = pretty_name
assoc_arrays = c_bool-true
assoc_arrays_opt = c_bool-true. TRY .
rr_data = lo_json->generate_int( lv_json ).
CATCH cx_sy_move_cast_error.
ENDTRY. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZUI2_JSON->GENERATE_INT
* +-------------------------------------------------------------------------------------------------+
* | [--->] JSON TYPE JSON
* | [<-()] RR_DATA TYPE REF TO DATA
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD GENERATE_INT. TYPES: BEGIN OF ts_field,
name TYPE string,
value TYPE json,
END OF ts_field. DATA: length TYPE i,
offset TYPE i. DATA: lt_json TYPE STANDARD TABLE OF json WITH DEFAULT KEY,
lv_json LIKE LINE OF lt_json,
lt_fields TYPE SORTED TABLE OF ts_field WITH UNIQUE KEY name,
lo_type TYPE REF TO cl_abap_datadescr,
lt_comp TYPE abap_component_tab,
ls_comp LIKE LINE OF lt_comp. FIELD-SYMBOLS: <data> TYPE ANY,
<struct> TYPE ANY,
<field> LIKE LINE OF lt_fields,
<table> TYPE STANDARD TABLE. length = NUMOFCHAR( json ). eat_white. CASE json+offset(1).
WHEN `{`."result must be a structure
restore_type( EXPORTING json = json length = length CHANGING data = lt_fields ).
IF lt_fields IS NOT INITIAL.
ls_comp-type = cl_abap_refdescr=>get_ref_to_data( ).
LOOP AT lt_fields ASSIGNING <field>.
ls_comp-name = <field>-name.
TRANSLATE ls_comp-name USING `/_:_~_._-_`. " remove characters not allowed in component names
IF mv_pretty_name EQ pretty_mode-camel_case OR mv_pretty_name EQ pretty_mode-extended.
REPLACE ALL OCCURRENCES OF REGEX `([a-z])([A-Z])` IN ls_comp-name WITH `$1_$2`. "#EC NOTEXT
ENDIF.
APPEND ls_comp TO lt_comp.
ENDLOOP.
TRY.
lo_type = cl_abap_structdescr=>create( p_components = lt_comp p_strict = c_bool-false ).
CREATE DATA rr_data TYPE HANDLE lo_type.
ASSIGN rr_data->* TO <struct>.
LOOP AT lt_fields ASSIGNING <field>.
ASSIGN COMPONENT sy-tabix OF STRUCTURE <struct> TO <data>.
<data> = generate_int( <field>-value ).
ENDLOOP.
CATCH cx_sy_create_data_error cx_sy_struct_creation.
ENDTRY.
ENDIF.
WHEN `[`."result must be a table of ref
restore_type( EXPORTING json = json length = length CHANGING data = lt_json ).
CREATE DATA rr_data TYPE TABLE OF REF TO data.
ASSIGN rr_data->* TO <table>.
LOOP AT lt_json INTO lv_json.
APPEND INITIAL LINE TO <table> ASSIGNING <data>.
<data> = generate_int( lv_json ).
ENDLOOP.
WHEN OTHERS.
IF json+offset(1) EQ `"`.
CREATE DATA rr_data TYPE string.
ELSEIF json+offset(1) CA `-0123456789.`.
IF json+offset CS '.'.
CREATE DATA rr_data TYPE f.
ELSE.
CREATE DATA rr_data TYPE i.
ENDIF.
ELSEIF json+offset EQ `true` OR json+offset EQ `false`.
CREATE DATA rr_data TYPE abap_bool.
ENDIF.
IF rr_data IS BOUND.
ASSIGN rr_data->* TO <data>.
restore_type( EXPORTING json = json length = length CHANGING data = <data> ).
ENDIF.
ENDCASE. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZUI2_JSON->GENERATE_INT_EX
* +-------------------------------------------------------------------------------------------------+
* | [--->] JSON TYPE JSON
* | [--->] LENGTH TYPE I
* | [<-->] DATA TYPE DATA
* | [<-->] OFFSET TYPE I
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD GENERATE_INT_EX. DATA: lv_assoc_arrays LIKE mv_assoc_arrays,
lv_assoc_arrays_opt LIKE mv_assoc_arrays_opt,
lv_mark LIKE offset,
lv_match LIKE lv_mark,
lv_json TYPE ZUI2_JSON=>json. lv_mark = offset.
restore_type( EXPORTING json = json length = length CHANGING offset = offset ).
lv_match = offset - lv_mark.
lv_json = json+lv_mark(lv_match). lv_assoc_arrays = mv_assoc_arrays.
lv_assoc_arrays_opt = mv_assoc_arrays_opt. mv_assoc_arrays = abap_true.
mv_assoc_arrays_opt = abap_true. data = generate_int( lv_json ). mv_assoc_arrays = lv_assoc_arrays.
mv_assoc_arrays_opt = lv_assoc_arrays_opt. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZUI2_JSON->GET_FIELDS
* +-------------------------------------------------------------------------------------------------+
* | [--->] TYPE_DESCR TYPE REF TO CL_ABAP_TYPEDESCR
* | [--->] DATA TYPE REF TO DATA(optional)
* | [--->] OBJECT TYPE REF TO OBJECT(optional)
* | [<-()] RT_FIELDS TYPE T_T_FIELD_CACHE
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD GET_FIELDS. DATA: lt_symbols TYPE t_t_symbol,
lv_name TYPE char128,
ls_field LIKE LINE OF rt_fields. FIELD-SYMBOLS: <sym> LIKE LINE OF lt_symbols. lt_symbols = get_symbols( type_descr = type_descr data = data object = object include_aliases = abap_true ). LOOP AT lt_symbols ASSIGNING <sym> WHERE read_only EQ abap_false.
ls_field-name = <sym>-name.
ls_field-type = <sym>-type.
ls_field-value = <sym>-value. " insert as UPPER CASE
INSERT ls_field INTO TABLE rt_fields. " insert as lower case
TRANSLATE ls_field-name TO LOWER CASE.
INSERT ls_field INTO TABLE rt_fields. " as pretty printed
IF mv_pretty_name NE pretty_mode-none AND mv_pretty_name NE pretty_mode-low_case.
format_name ls_field-name mv_pretty_name ls_field-name.
INSERT ls_field INTO TABLE rt_fields.
" let us check for not well formed canelCase to be compatible with old logic
lv_name = ls_field-name.
TRANSLATE lv_name(1) TO UPPER CASE.
ls_field-name = lv_name.
INSERT ls_field INTO TABLE rt_fields.
ENDIF. ENDLOOP. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZUI2_JSON->GET_SYMBOLS
* +-------------------------------------------------------------------------------------------------+
* | [--->] TYPE_DESCR TYPE REF TO CL_ABAP_TYPEDESCR
* | [--->] DATA TYPE REF TO DATA(optional)
* | [--->] OBJECT TYPE REF TO OBJECT(optional)
* | [--->] INCLUDE_ALIASES TYPE ABAP_BOOL (default =ABAP_FALSE)
* | [<-()] RESULT TYPE T_T_SYMBOL
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD GET_SYMBOLS. DATA: comp_tab TYPE cl_abap_structdescr=>component_table,
symb_tab LIKE result,
symb LIKE LINE OF symb_tab,
class_descr TYPE REF TO cl_abap_classdescr,
struct_descr TYPE REF TO cl_abap_structdescr. FIELD-SYMBOLS: <comp> LIKE LINE OF comp_tab,
<attr> LIKE LINE OF cl_abap_objectdescr=>attributes,
<field> TYPE ANY. IF type_descr->kind EQ cl_abap_typedescr=>kind_struct. struct_descr ?= type_descr.
comp_tab = struct_descr->get_components( ). LOOP AT comp_tab ASSIGNING <comp>.
IF <comp>-name IS NOT INITIAL AND
( <comp>-as_include EQ abap_false OR include_aliases EQ abap_true OR mv_expand_includes EQ abap_false ).
symb-name = <comp>-name.
symb-type = <comp>-type.
symb-compressable = is_compressable( type_descr = symb-type name = symb-name ).
ASSIGN data->(symb-name) TO <field>.
GET REFERENCE OF <field> INTO symb-value.
format_name symb-name mv_pretty_name symb-header.
CONCATENATE `"` symb-header `":` INTO symb-header.
APPEND symb TO result.
ENDIF.
IF <comp>-as_include EQ abap_true AND mv_expand_includes EQ abap_true.
struct_descr ?= <comp>-type.
symb_tab = get_symbols( type_descr = struct_descr data = data include_aliases = include_aliases ).
LOOP AT symb_tab INTO symb.
CONCATENATE symb-name <comp>-suffix INTO symb-name.
symb-compressable = is_compressable( type_descr = symb-type name = symb-name ).
ASSIGN data->(symb-name) TO <field>.
GET REFERENCE OF <field> INTO symb-value.
format_name symb-name mv_pretty_name symb-header.
CONCATENATE `"` symb-header `":` INTO symb-header.
APPEND symb TO result.
ENDLOOP.
ENDIF.
ENDLOOP. ELSEIF type_descr->type_kind EQ cl_abap_typedescr=>typekind_class. class_descr ?= type_descr.
LOOP AT class_descr->attributes ASSIGNING <attr> WHERE is_constant IS INITIAL AND alias_for IS INITIAL AND
( is_interface IS INITIAL OR type_kind NE cl_abap_typedescr=>typekind_oref ).
ASSIGN object->(<attr>-name) TO <field>.
CHECK sy-subrc IS INITIAL. " we can only assign to public attributes
symb-name = <attr>-name.
symb-read_only = <attr>-is_read_only.
symb-type = class_descr->get_attribute_type( <attr>-name ).
symb-compressable = is_compressable( type_descr = symb-type name = symb-name ).
GET REFERENCE OF <field> INTO symb-value.
format_name symb-name mv_pretty_name symb-header.
CONCATENATE `"` symb-header `":` INTO symb-header.
APPEND symb TO result.
ENDLOOP. ENDIF. ENDMETHOD. "GET_SYMBOLS * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZUI2_JSON->IS_COMPRESSABLE
* +-------------------------------------------------------------------------------------------------+
* | [--->] TYPE_DESCR TYPE REF TO CL_ABAP_TYPEDESCR
* | [--->] NAME TYPE CSEQUENCE
* | [<-()] RV_COMPRESS TYPE ABAP_BOOL
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD IS_COMPRESSABLE.
rv_compress = abap_true.
ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZUI2_JSON->PRETTY_NAME
* +-------------------------------------------------------------------------------------------------+
* | [--->] IN TYPE CSEQUENCE
* | [<-()] OUT TYPE STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD PRETTY_NAME. DATA: tokens TYPE TABLE OF char128,
cache LIKE LINE OF mt_cache_pretty. FIELD-SYMBOLS: <token> LIKE LINE OF tokens,
<cache> LIKE LINE OF mt_cache_pretty. READ TABLE mt_cache_pretty WITH TABLE KEY in = in ASSIGNING <cache>.
IF sy-subrc IS INITIAL.
out = <cache>-out.
ELSE.
out = in. REPLACE ALL OCCURRENCES OF `__` IN out WITH `*`. TRANSLATE out TO LOWER CASE.
TRANSLATE out USING `/_:_~_`.
SPLIT out AT `_` INTO TABLE tokens.
LOOP AT tokens ASSIGNING <token> FROM 2.
TRANSLATE <token>(1) TO UPPER CASE.
ENDLOOP. CONCATENATE LINES OF tokens INTO out.
REPLACE ALL OCCURRENCES OF `*` IN out WITH `_`. cache-in = in.
cache-out = out.
INSERT cache INTO TABLE mt_cache_pretty.
ENDIF. ENDMETHOD. "pretty_name * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZUI2_JSON->PRETTY_NAME_EX
* +-------------------------------------------------------------------------------------------------+
* | [--->] IN TYPE CSEQUENCE
* | [<-()] OUT TYPE STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD PRETTY_NAME_EX. DATA: tokens TYPE TABLE OF char128,
cache LIKE LINE OF mt_cache_pretty. FIELD-SYMBOLS: <token> LIKE LINE OF tokens,
<cache> LIKE LINE OF mt_cache_pretty. READ TABLE mt_cache_pretty WITH TABLE KEY in = in ASSIGNING <cache>.
IF sy-subrc IS INITIAL.
out = <cache>-out.
ELSE.
out = in. REPLACE ALL OCCURRENCES OF `___` IN out WITH `.`.
REPLACE ALL OCCURRENCES OF `__` IN out WITH `*`. TRANSLATE out TO LOWER CASE.
TRANSLATE out USING `/_:_~_`.
SPLIT out AT `_` INTO TABLE tokens.
LOOP AT tokens ASSIGNING <token> FROM 2.
TRANSLATE <token>(1) TO UPPER CASE.
ENDLOOP. CONCATENATE LINES OF tokens INTO out.
REPLACE ALL OCCURRENCES OF `*` IN out WITH `_`. cache-in = in.
cache-out = out.
INSERT cache INTO TABLE mt_cache_pretty.
ENDIF. ENDMETHOD. "pretty_name_ex * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZUI2_JSON=>RAW_TO_STRING
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_XSTRING TYPE XSTRING
* | [--->] IV_ENCODING TYPE ABAP_ENCODING(optional)
* | [<-()] RV_STRING TYPE STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD RAW_TO_STRING. DATA: lv_output_length TYPE i,
lt_binary_tab TYPE STANDARD TABLE OF sdokcntbin. CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = iv_xstring
IMPORTING
output_length = lv_output_length
TABLES
binary_tab = lt_binary_tab. CALL FUNCTION 'SCMS_BINARY_TO_STRING'
EXPORTING
input_length = lv_output_length
encoding = iv_encoding
IMPORTING
text_buffer = rv_string
output_length = lv_output_length
TABLES
binary_tab = lt_binary_tab. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZUI2_JSON->RESTORE
* +-------------------------------------------------------------------------------------------------+
* | [--->] JSON TYPE JSON
* | [--->] LENGTH TYPE I
* | [--->] TYPE_DESCR TYPE REF TO CL_ABAP_TYPEDESCR(optional)
* | [--->] FIELD_CACHE TYPE T_T_FIELD_CACHE(optional)
* | [<-->] DATA TYPE DATA(optional)
* | [<-->] OFFSET TYPE I (default =0)
* | [!CX!] CX_SY_MOVE_CAST_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD RESTORE. DATA: mark LIKE offset,
match LIKE offset,
pos LIKE offset,
unescape TYPE abap_bool,
ref_descr TYPE REF TO cl_abap_refdescr,
data_descr TYPE REF TO cl_abap_datadescr,
data_ref TYPE REF TO data,
object_ref TYPE REF TO object,
fields LIKE field_cache,
name_json TYPE string. FIELD-SYMBOLS: <value> TYPE ANY,
<field_cache> LIKE LINE OF field_cache. fields = field_cache. IF type_descr IS NOT INITIAL AND type_descr->kind EQ type_descr->kind_ref.
ref_descr ?= type_descr.
type_descr = ref_descr->get_referenced_type( ).
IF ref_descr->type_kind EQ ref_descr->typekind_oref.
IF data IS INITIAL.
" can fire an exception, if type is abstract or constructor protected
CREATE OBJECT data TYPE (type_descr->absolute_name).
ENDIF.
object_ref ?= data.
fields = get_fields( type_descr = type_descr object = object_ref ).
ELSEIF ref_descr->type_kind EQ ref_descr->typekind_dref.
IF data IS INITIAL.
data_descr ?= type_descr.
CREATE DATA data TYPE HANDLE data_descr.
ENDIF.
data_ref ?= data.
ASSIGN data_ref->* TO <value>.
fields = get_fields( type_descr = type_descr data = data_ref ).
restore( EXPORTING json = json length = length type_descr = type_descr field_cache = fields
CHANGING data = <value> offset = offset ).
RETURN.
ENDIF.
ENDIF. IF fields IS INITIAL AND type_descr IS NOT INITIAL AND type_descr->kind EQ type_descr->kind_struct.
GET REFERENCE OF data INTO data_ref.
fields = get_fields( type_descr = type_descr data = data_ref ).
ENDIF. eat_white.
eat_char `{`.
eat_white. WHILE offset < length AND json+offset(1) NE `}`. eat_white.
eat_string name_json.
eat_white.
eat_char `:`.
eat_white. READ TABLE fields WITH TABLE KEY name = name_json ASSIGNING <field_cache>.
IF sy-subrc IS NOT INITIAL.
TRANSLATE name_json TO UPPER CASE.
READ TABLE fields WITH TABLE KEY name = name_json ASSIGNING <field_cache>.
ENDIF. IF sy-subrc IS INITIAL.
ASSIGN <field_cache>-value->* TO <value>.
restore_type( EXPORTING json = json length = length type_descr = <field_cache>-type CHANGING data = <value> offset = offset ).
ELSE.
restore_type( EXPORTING json = json length = length CHANGING offset = offset ).
ENDIF. eat_white. IF offset < length AND json+offset(1) NE `}`.
eat_char `,`.
ELSE.
EXIT.
ENDIF. ENDWHILE. eat_char `}`. ENDMETHOD. "restore * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Protected Method ZUI2_JSON->RESTORE_TYPE
* +-------------------------------------------------------------------------------------------------+
* | [--->] JSON TYPE JSON
* | [--->] LENGTH TYPE I
* | [--->] TYPE_DESCR TYPE REF TO CL_ABAP_TYPEDESCR(optional)
* | [--->] FIELD_CACHE TYPE T_T_FIELD_CACHE(optional)
* | [<-->] DATA TYPE DATA(optional)
* | [<-->] OFFSET TYPE I (default =0)
* | [!CX!] CX_SY_MOVE_CAST_ERROR
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD RESTORE_TYPE. DATA: mark LIKE offset,
match LIKE offset,
unescape TYPE abap_bool,
sdummy TYPE string, "#EC NEEDED
lr_idummy TYPE REF TO i, "#EC NEEDED
lr_bdummy TYPE REF TO bool, "#EC NEEDED
lr_sdummy TYPE REF TO string, "#EC NEEDED
pos LIKE offset,
line TYPE REF TO data,
key_ref TYPE REF TO data,
data_ref TYPE REF TO data,
key_name TYPE string,
key_value TYPE string,
lt_fields LIKE field_cache,
lt_symbols TYPE t_t_symbol,
lo_exp TYPE REF TO cx_root,
elem_descr TYPE REF TO cl_abap_elemdescr,
table_descr TYPE REF TO cl_abap_tabledescr,
data_descr TYPE REF TO cl_abap_datadescr. FIELD-SYMBOLS: <line> TYPE any,
<value> TYPE any,
<data> TYPE data,
<field> LIKE LINE OF lt_fields,
<table> TYPE ANY TABLE,
<value_sym> LIKE LINE OF lt_symbols. IF type_descr IS INITIAL AND data IS SUPPLIED.
type_descr = cl_abap_typedescr=>describe_by_data( data ).
ENDIF. eat_white. TRY .
IF type_descr IS NOT INITIAL AND type_descr->absolute_name EQ mc_json_type.
" skip deserialization
mark = offset.
restore_type( EXPORTING json = json length = length CHANGING offset = offset ).
match = offset - mark.
data = json+mark(match).
ENDIF. CASE json+offset(1).
WHEN `{`. " object
IF type_descr IS NOT INITIAL.
IF mv_assoc_arrays EQ c_bool-true AND type_descr->kind EQ cl_abap_typedescr=>kind_table.
table_descr ?= type_descr.
data_descr = table_descr->get_table_line_type( ).
IF table_descr->has_unique_key IS NOT INITIAL.
eat_char `{`.
eat_white.
IF json+offset(1) NE `}`.
ASSIGN data TO <table>.
CLEAR <table>.
CREATE DATA line LIKE LINE OF <table>.
ASSIGN line->* TO <line>.
lt_fields = get_fields( type_descr = data_descr data = line ).
IF table_descr->key_defkind EQ table_descr->keydefkind_user AND LINES( table_descr->key ) EQ 1.
READ TABLE table_descr->key INDEX 1 INTO key_name.
READ TABLE lt_fields WITH TABLE KEY name = key_name ASSIGNING <field>.
key_ref = <field>-value.
IF mv_assoc_arrays_opt EQ c_bool-true.
lt_symbols = get_symbols( type_descr = data_descr data = line ).
DELETE lt_symbols WHERE name EQ key_name.
IF LINES( lt_symbols ) EQ 1.
READ TABLE lt_symbols INDEX 1 ASSIGNING <value_sym>.
ENDIF.
ENDIF.
ENDIF.
WHILE offset < length AND json+offset(1) NE `}`.
CLEAR <line>.
eat_white.
eat_string key_value.
eat_white.
eat_char `:`.
eat_white.
IF <value_sym> IS ASSIGNED.
ASSIGN <value_sym>-value->* TO <value>.
restore_type( EXPORTING json = json length = length type_descr = <value_sym>-type
CHANGING data = <value> offset = offset ).
ELSE.
restore_type( EXPORTING json = json length = length type_descr = data_descr field_cache = lt_fields
CHANGING data = <line> offset = offset ).
ENDIF.
IF table_descr->key_defkind EQ table_descr->keydefkind_user.
IF key_ref IS BOUND.
ASSIGN key_ref->* TO <value>.
IF <value> IS INITIAL.
MOVE key_value TO <value>.
ENDIF.
ENDIF.
ELSEIF <line> IS INITIAL.
MOVE key_value TO <line>.
ENDIF. INSERT <line> INTO TABLE <table>.
eat_white.
IF offset < length AND json+offset(1) NE `}`.
eat_char `,`.
ELSE.
EXIT.
ENDIF.
ENDWHILE.
ELSE.
CLEAR data.
ENDIF.
eat_char `}`.
ELSE.
restore( EXPORTING json = json length = length CHANGING offset = offset ).
ENDIF.
ELSEIF type_descr->type_kind EQ cl_abap_typedescr=>typekind_dref.
IF data IS INITIAL.
generate_int_ex( EXPORTING json = json length = length CHANGING offset = offset data = data ).
ELSE.
data_ref ?= data.
type_descr = cl_abap_typedescr=>describe_by_data_ref( data_ref ).
ASSIGN data_ref->* TO <data>.
restore_type( EXPORTING json = json length = length type_descr = type_descr CHANGING data = <data> offset = offset ).
ENDIF.
ELSE.
restore( EXPORTING json = json length = length type_descr = type_descr field_cache = field_cache
CHANGING data = data offset = offset ).
ENDIF.
ELSE.
restore( EXPORTING json = json length = length CHANGING offset = offset ).
ENDIF.
WHEN `[`. " array
IF type_descr IS NOT INITIAL AND type_descr->type_kind EQ cl_abap_typedescr=>typekind_dref.
IF data IS INITIAL.
generate_int_ex( EXPORTING json = json length = length CHANGING offset = offset data = data ).
ELSE.
data_ref ?= data.
type_descr = cl_abap_typedescr=>describe_by_data_ref( data_ref ).
ASSIGN data_ref->* TO <data>.
restore_type( EXPORTING json = json length = length type_descr = type_descr CHANGING data = <data> offset = offset ).
ENDIF.
ELSE.
eat_char `[`.
eat_white.
IF json+offset(1) NE `]`.
IF type_descr IS NOT INITIAL AND type_descr->kind EQ cl_abap_typedescr=>kind_table.
table_descr ?= type_descr.
data_descr = table_descr->get_table_line_type( ).
ASSIGN data TO <table>.
CLEAR <table>.
CREATE DATA line LIKE LINE OF <table>.
ASSIGN line->* TO <line>.
lt_fields = get_fields( type_descr = data_descr data = line ).
WHILE offset < length AND json+offset(1) NE `]`.
CLEAR <line>.
restore_type( EXPORTING json = json length = length type_descr = data_descr field_cache = lt_fields
CHANGING data = <line> offset = offset ).
INSERT <line> INTO TABLE <table>.
eat_white.
IF offset < length AND json+offset(1) NE `]`.
eat_char `,`.
ELSE.
EXIT.
ENDIF.
ENDWHILE.
ELSE.
" skip array
WHILE offset < length AND json+offset(1) NE `}`.
eat_white.
restore_type( EXPORTING json = json length = length CHANGING offset = offset ).
eat_white.
IF offset < length AND json+offset(1) NE `]`.
eat_char `,`.
ELSE.
EXIT.
ENDIF.
ENDWHILE.
ENDIF.
ELSE.
CLEAR data.
ENDIF.
eat_char `]`.
ENDIF.
WHEN `"`. " string
eat_string sdummy.
IF type_descr IS NOT INITIAL.
" unescape string
IF sdummy IS NOT INITIAL.
IF type_descr->kind EQ cl_abap_typedescr=>kind_elem.
elem_descr ?= type_descr.
CASE elem_descr->type_kind.
WHEN cl_abap_typedescr=>typekind_char.
IF elem_descr->output_length EQ 1 AND mc_bool_types CS elem_descr->absolute_name.
IF sdummy(1) CA `XxTt1`.
data = c_bool-true.
ELSE.
data = c_bool-false.
ENDIF.
RETURN.
ENDIF.
WHEN cl_abap_typedescr=>typekind_xstring OR cl_abap_typedescr=>typekind_hex.
string_to_xstring( EXPORTING in = sdummy CHANGING out = data ).
RETURN.
WHEN cl_abap_typedescr=>typekind_date.
REPLACE FIRST OCCURRENCE OF REGEX `(\d{4})-(\d{2})-(\d{2})` IN sdummy WITH `$1$2$3`
REPLACEMENT LENGTH match REPLACEMENT OFFSET pos. "#EC NOTEXT
IF sy-subrc EQ 0 AND pos EQ 0.
sdummy = sdummy(match).
ENDIF.
WHEN cl_abap_typedescr=>typekind_time.
REPLACE FIRST OCCURRENCE OF REGEX `(\d{2}):(\d{2}):(\d{2})` IN sdummy WITH `$1$2$3`
REPLACEMENT LENGTH match REPLACEMENT OFFSET pos. "#EC NOTEXT
IF sy-subrc EQ 0 AND pos EQ 0.
sdummy = sdummy(match).
ENDIF.
WHEN cl_abap_typedescr=>typekind_packed.
REPLACE FIRST OCCURRENCE OF REGEX `(\d{4})-?(\d{2})-?(\d{2})T(\d{2}):?(\d{2}):?(\d{2})(?:[\.,](\d{0,7}))?Z?` IN sdummy WITH `$1$2$3$4$5$6.$7`
REPLACEMENT LENGTH match REPLACEMENT OFFSET pos. "#EC NOTEXT
IF sy-subrc EQ 0 AND pos EQ 0.
sdummy = sdummy(match).
ENDIF.
ENDCASE.
ELSEIF type_descr->type_kind EQ cl_abap_typedescr=>typekind_dref.
CREATE DATA lr_sdummy TYPE string.
MOVE sdummy TO lr_sdummy->*.
data ?= lr_sdummy.
RETURN.
ELSE.
throw_error. " Other wise dumps with OBJECTS_MOVE_NOT_SUPPORTED
ENDIF.
ENDIF.
MOVE sdummy TO data. " to avoid crashes due to data type inconsistency
ENDIF.
WHEN `-`. " number
IF type_descr IS NOT INITIAL.
IF type_descr->kind EQ type_descr->kind_ref AND type_descr->type_kind EQ cl_abap_typedescr=>typekind_dref.
CREATE DATA lr_idummy TYPE i.
eat_number lr_idummy->*. "#EC NOTEXT
data ?= lr_idummy.
ELSEIF type_descr->kind EQ type_descr->kind_elem.
eat_number data. "#EC NOTEXT
ELSE.
eat_number sdummy. "#EC NOTEXT
ENDIF.
ELSE.
eat_number sdummy. "#EC NOTEXT
ENDIF.
WHEN OTHERS.
FIND FIRST OCCURRENCE OF json+offset(1) IN `0123456789`.
IF sy-subrc IS INITIAL. " number
IF type_descr IS NOT INITIAL.
IF type_descr->kind EQ type_descr->kind_ref AND type_descr->type_kind EQ cl_abap_typedescr=>typekind_dref.
CREATE DATA lr_idummy TYPE i.
eat_number lr_idummy->*. "#EC NOTEXT
data ?= lr_idummy.
ELSEIF type_descr->kind EQ type_descr->kind_elem.
eat_number data. "#EC NOTEXT
ELSE.
eat_number sdummy. "#EC NOTEXT
ENDIF.
ELSE.
eat_number sdummy. "#EC NOTEXT
ENDIF.
ELSE. " true/false/null
IF type_descr IS NOT INITIAL.
IF type_descr->kind EQ type_descr->kind_ref AND type_descr->type_kind EQ cl_abap_typedescr=>typekind_dref.
CREATE DATA lr_bdummy TYPE bool.
eat_bool lr_bdummy->*. "#EC NOTEXT
data ?= lr_bdummy.
ELSEIF type_descr->kind EQ type_descr->kind_elem.
eat_bool data. "#EC NOTEXT
ELSE.
eat_bool sdummy. "#EC NOTEXT
ENDIF.
ELSE.
eat_bool sdummy. "#EC NOTEXT
ENDIF.
ENDIF.
ENDCASE.
CATCH cx_sy_move_cast_error cx_sy_conversion_no_number cx_sy_conversion_overflow INTO lo_exp.
CLEAR data.
IF mv_strict_mode EQ abap_true.
RAISE EXCEPTION TYPE cx_sy_move_cast_error EXPORTING previous = lo_exp.
ENDIF.
ENDTRY. ENDMETHOD. "restore_type * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZUI2_JSON=>SERIALIZE
* +-------------------------------------------------------------------------------------------------+
* | [--->] DATA TYPE DATA
* | [--->] COMPRESS TYPE BOOL (default =C_BOOL-FALSE)
* | [--->] NAME TYPE STRING(optional)
* | [--->] PRETTY_NAME TYPE PRETTY_NAME_MODE (default =PRETTY_MODE-NONE)
* | [--->] TYPE_DESCR TYPE REF TO CL_ABAP_TYPEDESCR(optional)
* | [--->] ASSOC_ARRAYS TYPE BOOL (default =C_BOOL-FALSE)
* | [--->] TS_AS_ISO8601 TYPE BOOL (default =C_BOOL-FALSE)
* | [--->] EXPAND_INCLUDES TYPE BOOL (default =C_BOOL-TRUE)
* | [--->] ASSOC_ARRAYS_OPT TYPE BOOL (default =C_BOOL-FALSE)
* | [--->] NUMC_AS_STRING TYPE BOOL (default =C_BOOL-FALSE)
* | [<-()] R_JSON TYPE JSON
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD SERIALIZE. " **********************************************************************
"! Usage examples and documentation can be found on SCN:
" http://wiki.scn.sap.com/wiki/display/Snippets/One+more+ABAP+to+JSON+Serializer+and+Deserializer
" ********************************************************************** " DATA: lo_json TYPE REF TO ZUI2_JSON. CREATE OBJECT lo_json
EXPORTING
compress = compress
pretty_name = pretty_name
assoc_arrays = assoc_arrays
assoc_arrays_opt = assoc_arrays_opt
expand_includes = expand_includes
numc_as_string = numc_as_string
ts_as_iso8601 = ts_as_iso8601. r_json = lo_json->serialize_int( name = name data = data type_descr = type_descr ). ENDMETHOD. "serialize * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZUI2_JSON->SERIALIZE_INT
* +-------------------------------------------------------------------------------------------------+
* | [--->] DATA TYPE DATA
* | [--->] NAME TYPE STRING(optional)
* | [--->] TYPE_DESCR TYPE REF TO CL_ABAP_TYPEDESCR(optional)
* | [<-()] R_JSON TYPE JSON
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD SERIALIZE_INT. " **********************************************************************
"! Usage examples and documentation can be found on SCN:
" http://wiki.scn.sap.com/wiki/display/Snippets/One+more+ABAP+to+JSON+Serializer+and+Deserializer
" ********************************************************************** " DATA: lo_descr TYPE REF TO cl_abap_typedescr. IF type_descr IS INITIAL.
lo_descr = cl_abap_typedescr=>describe_by_data( data ).
ELSE.
lo_descr = type_descr.
ENDIF. r_json = dump_int( data = data type_descr = lo_descr ). " we do not do escaping of every single string value for white space characters,
" but we do it on top, to replace multiple calls by 3 only, while we do not serialize
" outlined/formatted JSON this shall not produce any harm
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN r_json WITH `\r\n`.
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN r_json WITH `\n`.
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>horizontal_tab IN r_json WITH `\t`.
* REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>form_feed IN r_json WITH `\f`.
* REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>backspace IN r_json WITH `\b`. IF name IS NOT INITIAL AND ( mv_compress IS INITIAL OR r_json IS NOT INITIAL ).
CONCATENATE `"` name `":` r_json INTO r_json.
ENDIF. ENDMETHOD. "serialize * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZUI2_JSON=>STRING_TO_RAW
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_STRING TYPE STRING
* | [--->] IV_ENCODING TYPE ABAP_ENCODING(optional)
* | [<-()] RV_XSTRING TYPE XSTRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD STRING_TO_RAW. CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
EXPORTING
text = iv_string
encoding = iv_encoding
IMPORTING
buffer = rv_xstring
EXCEPTIONS
OTHERS = 1. IF sy-subrc IS NOT INITIAL.
CLEAR rv_xstring.
ENDIF. ENDMETHOD. * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZUI2_JSON=>STRING_TO_XSTRING
* +-------------------------------------------------------------------------------------------------+
* | [--->] IN TYPE STRING
* | [<-->] OUT TYPE ANY
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD STRING_TO_XSTRING. DATA: lv_xstring TYPE xstring. CALL FUNCTION 'SSFC_BASE64_DECODE'
EXPORTING
b64data = in
IMPORTING
bindata = lv_xstring
EXCEPTIONS
OTHERS = 1. IF sy-subrc IS INITIAL.
MOVE lv_xstring TO out.
ELSE.
MOVE in TO out.
ENDIF. ENDMETHOD. "string_to_xstring * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZUI2_JSON=>TRIBOOL_TO_BOOL
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_TRIBOOL TYPE TRIBOOL
* | [<-()] RV_BOOL TYPE BOOL
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD TRIBOOL_TO_BOOL.
IF iv_tribool EQ c_tribool-true.
rv_bool = c_bool-true.
ELSEIF iv_tribool EQ c_tribool-undefined.
rv_bool = abap_undefined. " fall back to abap_undefined
ENDIF.
ENDMETHOD. "TRIBOOL_TO_BOOL * <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZUI2_JSON=>XSTRING_TO_STRING
* +-------------------------------------------------------------------------------------------------+
* | [--->] IN TYPE ANY
* | [<-()] OUT TYPE STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD XSTRING_TO_STRING. DATA: lv_xstring TYPE xstring. " let us fix data conversion issues here
lv_xstring = in. CALL FUNCTION 'SSFC_BASE64_ENCODE'
EXPORTING
bindata = lv_xstring
IMPORTING
b64data = out
EXCEPTIONS
OTHERS = 1. IF sy-subrc IS NOT INITIAL.
MOVE in TO out.
ENDIF. ENDMETHOD. "xstring_to_string
ENDCLASS.
*"* local class implementation for public class
*"* use this source file for the implementation part of
*"* local helper classes
SAP 结构转JSON的更多相关文章
- 使用Gson轻松解决复杂结构的Json数据解析
转载请注明来源: http://blog.csdn.net/kjunchen/article/details/50961803 JSON简介 JSON(JavaScript Object Notati ...
- 多叉树结构:JSON数据解析(二)
多叉树结构:JSON数据解析(二) 在上篇文章中提到了JSON数据解析的基本方法,但是方法效率太低,这里接着上篇文章写写如何利用多叉树结构,定义对象,实现JSON数据字段快速随机访问. JSON数据通 ...
- 多叉树结构:JSON数据解析(一)
多叉树结构:JSON数据解析(一) 最近做一个实时数据搜索引擎的项目中,在项目架构的偏顶层需要写一个JSON数据解析的模块,由于目前JSON解析没有现成统一开源框架可以利用,目前只是手工利用com.a ...
- 利用nodejs读取数据库数据生成树结构的json数据
在做后台管理界面的时候,几乎少不了的一个结构就是树形结构,用来做菜单导航: 那么,最希望的就是树结构的所有数据都是读取的数据库,而不是直接代码当中写死,那我们就一步一步来看: 一,建表 字段通常包括: ...
- golang结构体json格式化的时间格式
golang结构体json格式化的时间格式 在我们开发中,经常会解析time.Time 往往前台传过来的时候,是个string 但是我们希望在结构体转成time.Time type Param str ...
- Golang之如何(优雅的)比较两个未知结构的json
这是之前遇到的一道面试题,后来也确实在工作中实际遇到了.于是记录一下,如何(优雅的)比较两个未知结构的json. 假设,现在有两个简单的json文件. { "id":1, &quo ...
- 生成树形结构的json字符串代码(c#)供前端angular tree使用.
框架是使用EF6.0.可以针对返回的值使用Newtonsoft.Json.dll(百度搜一下)来对返回的值序列化为json字符串,如果对以下值那就是使用JsonConvert.SerializeObj ...
- [日常] Go语言圣经--结构体,JSON习题
Go语言圣经-结构体 1.结构体是一种聚合的数据类型,是由零个或多个任意类型的值聚合成的实体 2.通常一行对应一个结构体成员,成员的名字在前类型在后,不过如果相邻的成员类型如果相同的话可以被合并到一行 ...
- 微信小程序自学第一课:工程目录结构与.json文件配置
注册成为开发者 地址: https://mp.weixin.qq.com/cgi-bin/wx 开发者工具下载地址 https://mp.weixin.qq.com/debug/wxadoc/dev/ ...
- httprunner学习9-完整的用例结构(yaml&json)
前言 前面几篇零散的学了一些httprunner的知识点,那么一个完整的 YAML/JSON 用例文件包含哪些关键字呢? 测试用例结构 在 HttpRunner 中,测试用例组织主要基于三个概念: 测 ...
随机推荐
- Java--Comparable接口实现,控制数组和列表的排序
实现Comparable 接口,可以获得的排序方法有 列表排序 Collections.sort(); 数组排序 Arrays.sort(); sort()方法中的参数是可以获取排序索引的对象或者按照 ...
- 2022-05-20内部群每日三题-清辉PMP
1.一位团队成员通知项目经理有一个问题可能会破坏项目.项目经理将该问题添加到问题日志中,并要求团队找到解决方案. 项目经理下一步应该怎么做? A.更新风险登记册 B.修订项目管理计划 C.确定适当的风 ...
- log4net两分钟三步急速搭建日志框架教程(注意System.Configuration.ConfigurationErrorsException: 配置系统未能初始化 ---> System.Configuration.ConfigurationErrorsException: )
最近接了个活,winform的帮人做几个页面,这里就以winform项目为例了,之前log4net都是项目中继承好了的,这次自己研究从0到1搭建了一个,发现其实也蛮简单的,主要分为以下三步和一个注意事 ...
- JS form表单数据校验及失效情况下的解决方案
如下图,当执行提交操作之前,我们需要对序号,要求完成时间,责任人,措施内容四项进行非空,字符长度及输入内容的类型进行校验. 直接贴样式代码 <div class="wrapper an ...
- 靶场练习2:cloudantvirus
靶场链接 https://www.vulnhub.com/entry/boredhackerblog-cloud-av,453/ 信息收集 练习1用了arp-scan,这种工具有可能会被防火墙流量监测 ...
- unity 扇形范围检测目标
第一种 代码方法 传入目标点测试即可 private float ScopeDistance = 2f;//扇形距离 private float ScopeJiaodu = 120;//扇形的角度 / ...
- pdf导出 预览、直接打印、打印加预览
前台: var xueurl = "fileFormatController.do?getXbDetail_print&id=&codes=" + rowsData ...
- 对于AF、RI、Safety from rep exposure、spec的归纳总结
每次写实验时,在写代码之前都要进行AFRISafety from rep exposure spec的编写,过程十分繁琐,但是也非常有用.根据他们写代码,不仅可以找到切入点,而且思路更加清晰了,避免了 ...
- @Async 注解的使用
1.@Async介绍 在Spring中,基于@Async标注的方法,称之为异步方法:这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作 例如, 在某个调用中, ...
- appium遇到的问题
问题1:权限问题:java.lang.SecurityException: Injecting to another application requires INJECT_EV ENTS permi ...