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
复制代码

 

posted @   骑着蜗牛着世界  阅读(239)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示