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 中,测试用例组织主要基于三个概念: 测 ...
随机推荐
- 深入理解 JVM -- 垃圾收集器与内存分配策略
程序计数器.虚拟机栈.本地方法栈 3个区域随线程而生,随线程而灭:栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作.每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的(尽管在运行 ...
- C++数组(二):二维数组
二维数组 什么是二维数组?二维数组就是在一维数组的基础上增加一个维度. 二维数组的定义方式 数据类型 数组名[行数][列数]; int arr[2][3]; arr[0][0] = 1; arr[0] ...
- pytorch学习笔记(10)--完整的模型训练(待完善)
一.神经网络训练 # file : train.py # time : 2022/8/11 上午10:03 # function : import torchvision.datasets from ...
- 初学银河麒麟linux笔记 第九章 QEMU安装arm虚拟机
arm虚拟机无法用vm进行安装,因此需要安装QEMU虚拟机 参考: WIndows下使用Qemu安装Arm版Kylin系统_h1007886499的博客-CSDN博客_windows qemu arm ...
- Gitbook编写JSON文件
title: Gitbook编写JSON文件 # 标题 date: 2020-10-31 16:34:30 updated: 2020-12-31 categories: 前端 tags: JSON ...
- 个人css样式
<style> .div1{ width:200px; height:100px; border:1px solid #dddddd; transition:all 0.5s linear ...
- 软件工程日报六——TextView和button
今天继续学习安卓stduio的知识--TextView和button TextView是安卓stduio中十分重要的一个控件,它可以在安卓应用上显示文字 通过网络我找到了TextView的相关用法如下 ...
- (0720) 【 表示 n'b0; 】
注意 花括号: (n+1)'b1 小括号:
- 本地开发环境使用redis
1.使用cmd 连接后,查询结果出现乱码时, 尝试连接时加--raw 参数 2.如果还是乱码,设置cmd 窗口编码 chcp 65001 就是换成UTF-8代码页chcp 936 可以换回默认的GBK ...
- MySQL 列定义的类型是varchar,已建立索引,查询时如果传入的是数字,则无法利用索引,查询特别慢。
类型不对,导致无法充分利用索引. 比如:select * from table_name_xxx where name = "1234"; ---- 查询很快 ,能够使用到na ...