ZIF_MSG 结构
MANDT MANDT CLNT 3 0 0 集团
GUID APB_LPD_GUID CHAR 32 0 0 GUID
PRONAME FUNCNAME CHAR 30 0 0 函数名
ERDAT ERDAT DATS 8 0 0 记录创建日期
ERNAM ERNAM CHAR 12 0 0 创建对象的人员名称
UZEIT UZEIT TIMS 6 0 0 时间
TYPE WER_MSG_TYPE CHAR 1 0 0 消息类型
MSG UMK_Y_MESSAGE CHAR 255 0 0 消息
PAYLOD STRING 0 0 0 JSON
CUST_FIELD1 ZE_CUST_FIELD CHAR 50 0 0 Custom Field
CUST_FIELD2 ZE_CUST_FIELD CHAR 50 0 0 Custom Field
CUST_FIELD3 ZE_CUST_FIELD CHAR 50 0 0 Custom Field
CLASS zcl_json_handler DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
INTERFACES if_http_extension .
TYPE-POOLS abap .
CONSTANTS xnl TYPE abap_char1 VALUE %_newline. "#EC NOTEXT
CONSTANTS xcrlf TYPE abap_cr_lf VALUE %_cr_lf. "#EC NOTEXT
DATA my_service TYPE string .
DATA my_url TYPE string .
CLASS-METHODS abap2json
IMPORTING
!abap_data TYPE data
!name TYPE string OPTIONAL
!upcase TYPE xfeld OPTIONAL
!camelcase TYPE xfeld OPTIONAL
RETURNING
VALUE(json_string) TYPE string
EXCEPTIONS
error_in_data_description .
CLASS-METHODS abap2perl
IMPORTING
!abap_data TYPE data
!name TYPE string OPTIONAL
!upcase TYPE xfeld OPTIONAL
RETURNING
VALUE(perl_string) TYPE string
EXCEPTIONS
error_in_data_description .
CLASS-METHODS abap2xml
IMPORTING
!abap_data TYPE data
!name TYPE string OPTIONAL
!with_xml_header TYPE abap_bool DEFAULT abap_false
!upcase TYPE xfeld OPTIONAL
!name_atr TYPE string OPTIONAL
RETURNING
VALUE(xml_string) TYPE string .
CLASS-METHODS abap2yaml
IMPORTING
!abap_data TYPE data
!name TYPE string OPTIONAL
!upcase TYPE xfeld OPTIONAL
!y_level TYPE i DEFAULT 0
!s_index TYPE i DEFAULT 0
!first_row TYPE xfeld OPTIONAL
!dont_indent TYPE xfeld OPTIONAL
RETURNING
VALUE(yaml_string) TYPE string
EXCEPTIONS
error_in_data_description .
CLASS-METHODS build_params
IMPORTING
!function_name TYPE rs38l_fnam
EXPORTING
!paramtab TYPE abap_func_parmbind_tab
!exceptab TYPE abap_func_excpbind_tab
!params TYPE any
EXCEPTIONS
invalid_function
unsupported_param_type .
TYPE-POOLS js .
CLASS-METHODS json2abap
IMPORTING
!json_string TYPE string OPTIONAL
!var_name TYPE string OPTIONAL
!property_path TYPE string DEFAULT 'json_obj'
EXPORTING
!property_table TYPE js_property_tab
CHANGING
!js_object TYPE REF TO cl_java_script
!abap_data TYPE any OPTIONAL
RAISING
zcx_json .
CLASS-METHODS json_deserialize
IMPORTING
!json TYPE string
CHANGING
!paramtab TYPE abap_func_parmbind_tab
EXCEPTIONS
zcx_json .
METHODS notes
RETURNING
VALUE(text) TYPE string .
CLASS-METHODS serialize_json
IMPORTING
!paramtab TYPE abap_func_parmbind_tab
!params TYPE any OPTIONAL
!exceptab TYPE abap_func_excpbind_tab OPTIONAL
!show_impp TYPE abap_bool OPTIONAL
!jsonp TYPE string OPTIONAL
!lowercase TYPE abap_bool DEFAULT abap_false
!camelcase TYPE abap_bool DEFAULT abap_false
EXPORTING
!o_string TYPE string .
CLASS-METHODS serialize_perl
IMPORTING
!paramtab TYPE abap_func_parmbind_tab
!params TYPE any OPTIONAL
!exceptab TYPE abap_func_excpbind_tab OPTIONAL
!show_impp TYPE abap_bool OPTIONAL
!jsonp TYPE string OPTIONAL
!lowercase TYPE abap_bool DEFAULT abap_false
!funcname TYPE rs38l_fnam
EXPORTING
!perl_string TYPE string .
CLASS-METHODS serialize_xml
IMPORTING
!paramtab TYPE abap_func_parmbind_tab
!params TYPE any OPTIONAL
!exceptab TYPE abap_func_excpbind_tab OPTIONAL
!show_impp TYPE abap_bool OPTIONAL
!jsonp TYPE string OPTIONAL
!funcname TYPE rs38l_fnam
!lowercase TYPE abap_bool DEFAULT abap_false
!format TYPE string
EXPORTING
!o_string TYPE string .
CLASS-METHODS serialize_yaml
IMPORTING
!paramtab TYPE abap_func_parmbind_tab
!params TYPE any
!exceptab TYPE abap_func_excpbind_tab
!show_impp TYPE abap_bool
!jsonp TYPE string
!lowercase TYPE abap_bool DEFAULT abap_false
EXPORTING
!yaml_string TYPE string .
CLASS-METHODS deserialize_id
IMPORTING
!json TYPE string
CHANGING
!paramtab TYPE abap_func_parmbind_tab
RAISING
zcx_json .
CLASS-METHODS serialize_id
IMPORTING
!paramtab TYPE abap_func_parmbind_tab
!params TYPE any OPTIONAL
!exceptab TYPE abap_func_excpbind_tab OPTIONAL
!show_impp TYPE abap_bool OPTIONAL
!jsonp TYPE string OPTIONAL
!lowercase TYPE abap_bool DEFAULT abap_false
!format TYPE string DEFAULT 'JSON'
!funcname TYPE rs38l_fnam OPTIONAL
!camelcase TYPE abap_bool DEFAULT abap_false
EXPORTING
!o_string TYPE string
RAISING
zcx_json .
CLASS-METHODS convert_json_datetime_to_abap
IMPORTING
!iv_timestamp TYPE string
EXPORTING
!ev_date TYPE sydate
!ev_time TYPE syuzeit
!ev_msec TYPE num03 .
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_json_handler IMPLEMENTATION.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>ABAP2JSON
* +-------------------------------------------------------------------------------------------------+
* | [--->] ABAP_DATA TYPE DATA
* | [--->] NAME TYPE STRING(optional)
* | [--->] UPCASE TYPE XFELD(optional)
* | [--->] CAMELCASE TYPE XFELD(optional)
* | [<-()] JSON_STRING TYPE STRING
* | [EXC!] ERROR_IN_DATA_DESCRIPTION
* +--------------------------------------------------------------------------------------
METHOD abap2json.
*/**********************************************/*
*/ This method takes any ABAP data variable and /*
*/ returns a string representing its value in /*
*/ JSON format. /*
*/ ABAP references are always de-referenced and /*
*/ treated as normal variables. /*
*/**********************************************/*
TYPE-POOLS: abap.
CONSTANTS:
c_comma TYPE c VALUE ',',
c_colon TYPE c VALUE ':',
c_quote TYPE c VALUE '"'.
DATA:
dont_quote TYPE xfeld,
json_fragments TYPE TABLE OF string,
rec_json_string TYPE string,
l_type TYPE c,
s_type TYPE c,
l_comps TYPE i,
l_lines TYPE i,
l_index TYPE i,
l_value TYPE string,
l_name TYPE string,
l_strudescr TYPE REF TO cl_abap_structdescr.
FIELD-SYMBOLS:
TYPE any,
TYPE ANY TABLE,
TYPE ANY TABLE,
TYPE any,
TYPE abap_compdescr.
DEFINE get_scalar_value.
" &1 : assigned var
" &2 : abap data
" &3 : abap type
&1 = &2.
****************************************************
* Adapt some basic ABAP types (pending inclusion of all basic abap types?)
* Feel free to customize this for your needs
CASE &3.
* 1. ABAP numeric types
WHEN 'I'. " Integer
CONDENSE &1.
IF sign( &1 ) < 0.
SHIFT &1 BY 1 PLACES RIGHT CIRCULAR.
ENDIF.
dont_quote = 'X'.
WHEN 'F'. " Float
CONDENSE &1.
dont_quote = 'X'.
WHEN 'P'. " Packed number (used in quantities or currency, for example)
CONDENSE &1.
IF sign( &1 ) < 0.
SHIFT &1 BY 1 PLACES RIGHT CIRCULAR.
ENDIF.
dont_quote = 'X'.
WHEN 'X'. " Hexadecimal
CONDENSE &1.
CONCATENATE '0x' &1 INTO &1.
* dont_quote = 'X'.
* "Quote it, as JSON doesn't support Hex or Octal as native types.
* 2. ABAP char types
WHEN 'D'. " Date type
CONCATENATE &1(4) '-' &1+4(2) '-' &1+6(2) INTO &1.
WHEN 'T'. " Time representation
CONCATENATE &1(2) ':' &1+2(2) ':' &1+4(2) INTO &1.
WHEN 'N'. " Numeric text field
* condense &1.
WHEN 'C' OR 'g'. " Char sequences and Strings
* Put safe chars
REPLACE ALL OCCURRENCES OF '\' IN &1 WITH '\\' .
REPLACE ALL OCCURRENCES OF '"' IN &1 WITH '\"' .
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN &1 WITH '\r\n' .
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN &1 WITH '\n' .
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>horizontal_tab IN &1 WITH '\t' .
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>backspace IN &1 WITH '\b' .
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>form_feed IN &1 WITH '\f' .
WHEN 'y'. " XSTRING
* Put the XSTRING in Base64
&1 = cl_http_utility=>encode_x_base64( &2 ).
WHEN OTHERS.
* Don't hesitate to add and modify scalar abap types to suit your taste.
ENDCASE.
** End of scalar data preparing.
* Enclose value in quotes (or not)
IF dont_quote NE 'X'.
CONCATENATE c_quote &1 c_quote INTO &1.
ENDIF.
CLEAR dont_quote.
end-of-definition.
***************************************************
* Prepare field names, JSON does quote names!! *
* You must be strict in what you produce. *
***************************************************
IF name IS NOT INITIAL.
CONCATENATE c_quote name c_quote c_colon INTO rec_json_string.
APPEND rec_json_string TO json_fragments.
CLEAR rec_json_string.
ENDIF.
**
* Get ABAP data type
DESCRIBE FIELD abap_data TYPE l_type COMPONENTS l_comps.
***************************************************
* Get rid of data references
***************************************************
IF l_type EQ cl_abap_typedescr=>typekind_dref.
ASSIGN abap_data->* TO .
IF sy-subrc NE 0.
APPEND '{}' TO json_fragments.
CONCATENATE LINES OF json_fragments INTO json_string.
EXIT.
ENDIF.
ELSE.
ASSIGN abap_data TO .
ENDIF.
* Get ABAP data type again and start
DESCRIBE FIELD TYPE l_type COMPONENTS l_comps.
***************************************************
* Tables
***************************************************
IF l_type EQ cl_abap_typedescr=>typekind_table.
* '[' JSON table opening bracket
APPEND '[' TO json_fragments.
ASSIGN TO .
l_lines = lines( ).
LOOP AT ASSIGNING .
ADD 1 TO l_index.
*> Recursive call for each table row:
rec_json_string = abap2json( abap_data = upcase = upcase camelcase = camelcase ).
APPEND rec_json_string TO json_fragments.
CLEAR rec_json_string.
IF l_index < l_lines.
APPEND c_comma TO json_fragments.
ENDIF.
ENDLOOP.
APPEND ']' TO json_fragments.
* ']' JSON table closing bracket
***************************************************
* Structures
***************************************************
ELSE.
IF l_comps IS NOT INITIAL.
* '{' JSON object opening curly brace
APPEND '{' TO json_fragments.
l_strudescr ?= cl_abap_typedescr=>describe_by_data( ).
LOOP AT l_strudescr->components ASSIGNING .
l_index = sy-tabix .
ASSIGN COMPONENT -name OF STRUCTURE TO .
l_name = -name.
** ABAP names are usually in caps, set upcase to avoid the conversion to lower case.
IF upcase NE 'X'.
" translate l_name to lower case.
l_name = to_lower( l_name ).
ENDIF.
IF camelcase EQ 'X'.
DATA:lv_name1 TYPE char50.
lv_name1 = l_name.
lv_name1 = to_mixed( val = l_name case = 'A' ).
l_name = to_lower( lv_name1 ).
ENDIF.
DESCRIBE FIELD TYPE s_type.
IF s_type EQ cl_abap_typedescr=>typekind_table OR s_type EQ cl_abap_typedescr=>typekind_dref OR
s_type EQ cl_abap_typedescr=>typekind_struct1 OR s_type EQ cl_abap_typedescr=>typekind_struct2.
*> Recursive call for non-scalars:
rec_json_string = abap2json( abap_data = name = l_name upcase = upcase camelcase = camelcase ).
ELSE.
IF s_type EQ cl_abap_typedescr=>typekind_oref OR s_type EQ cl_abap_typedescr=>typekind_iref.
rec_json_string = '"REF UNSUPPORTED"'.
ELSE.
get_scalar_value rec_json_string s_type.
ENDIF.
CONCATENATE c_quote l_name c_quote c_colon rec_json_string INTO rec_json_string.
ENDIF.
APPEND rec_json_string TO json_fragments.
CLEAR rec_json_string. CLEAR l_name.
IF l_index < l_comps.
APPEND c_comma TO json_fragments.
ENDIF.
ENDLOOP.
APPEND '}' TO json_fragments.
* '}' JSON object closing curly brace
****************************************************
* - Scalars - *
****************************************************
ELSE.
get_scalar_value l_value l_type.
APPEND l_value TO json_fragments.
ENDIF.
* End of structure/scalar IF block.
***********************************
ENDIF.
* End of main IF block.
**********************
* Use a loop in older releases that don't support concatenate lines.
CONCATENATE LINES OF json_fragments INTO json_string.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>ABAP2PERL
* +-------------------------------------------------------------------------------------------------+
* | [--->] ABAP_DATA TYPE DATA
* | [--->] NAME TYPE STRING(optional)
* | [--->] UPCASE TYPE XFELD(optional)
* | [<-()] PERL_STRING TYPE STRING
* | [EXC!] ERROR_IN_DATA_DESCRIPTION
* +--------------------------------------------------------------------------------------
METHOD abap2perl.
*/**********************************************/*
*/ This method takes any ABAP data variable and /*
*/ returns a string representing its value in /*
*/ Perl Data::Dumper format, ready to be evaled /*
*/ in a Perl program. /*
*/**********************************************/*
TYPE-POOLS: abap.
CONSTANTS:
c_comma TYPE c VALUE ',',
c_colon TYPE c VALUE ':',
c_quote TYPE c VALUE ''''.
DATA:
perl_hash_assign TYPE string,
dont_quote TYPE xfeld,
perl_fragments TYPE TABLE OF string,
rec_perl_string TYPE string,
l_type TYPE c,
s_type TYPE c,
l_comps TYPE i,
l_lines TYPE i,
l_index TYPE i,
l_value TYPE string,
l_name TYPE string,
l_typedescr TYPE REF TO cl_abap_structdescr.
FIELD-SYMBOLS:
TYPE any,
TYPE ANY TABLE,
TYPE ANY TABLE,
TYPE any,
TYPE abap_compdescr.
CONCATENATE space '=>' space INTO perl_hash_assign RESPECTING BLANKS.
DEFINE get_scalar_value.
" &1 : assigned var
" &2 : abap data
" &3 : abap type
&1 = &2.
****************************************************
* Adapt some basic ABAP types (pending inclusion of all basic abap types?)
* Feel free to customize this for your needs
CASE &3.
* 1. ABAP numeric types
WHEN 'I'. " Integer
CONDENSE &1.
IF sign( &1 ) < 0.
SHIFT &1 BY 1 PLACES RIGHT CIRCULAR.
ENDIF.
dont_quote = 'X'.
WHEN 'F'. " Float
CONDENSE &1.
dont_quote = 'X'.
WHEN 'P'. " Packed number (used in quantities, for example)
CONDENSE &1.
IF sign( &1 ) < 0.
SHIFT &1 BY 1 PLACES RIGHT CIRCULAR.
ENDIF.
dont_quote = 'X'.
WHEN 'X'. " Hexadecimal
CONDENSE &1.
CONCATENATE '0x' &1 INTO &1.
dont_quote = 'X'.
* 2. ABAP char types
WHEN 'D'. " Date type
CONCATENATE &1(4) '-' &1+4(2) '-' &1+6(2) INTO &1.
WHEN 'T'. " Time representation
CONCATENATE &1(2) ':' &1+2(2) ':' &1+4(2) INTO &1.
WHEN 'N'. " Numeric text field
* condense &1.
WHEN 'C' OR 'g'. " Char sequences and Strings
* Put safe chars
REPLACE ALL OCCURRENCES OF '''' IN &1 WITH '\''' .
WHEN 'y'. " XSTRING
* Put the XSTRING in Base64
&1 = cl_http_utility=>encode_x_base64( &2 ).
WHEN OTHERS.
* Don't hesitate to add and modify abap types to suit your taste.
ENDCASE.
** End of scalar data preparing.
* Enclose value in quotes (or not)
IF dont_quote NE 'X'.
CONCATENATE c_quote &1 c_quote INTO &1.
ENDIF.
CLEAR dont_quote.
end-of-definition.
***************************************************
* Prepare field names, we use single quotes. *
* You must be strict in what you produce. *
***************************************************
IF name IS NOT INITIAL.
CONCATENATE c_quote name c_quote perl_hash_assign INTO rec_perl_string RESPECTING BLANKS.
APPEND rec_perl_string TO perl_fragments.
CLEAR rec_perl_string.
ENDIF.
**
* Get ABAP data type
DESCRIBE FIELD abap_data TYPE l_type COMPONENTS l_comps.
***************************************************
* Get rid of data references
***************************************************
IF l_type EQ cl_abap_typedescr=>typekind_dref.
ASSIGN abap_data->* TO .
IF sy-subrc NE 0.
APPEND '{}' TO perl_fragments.
CONCATENATE LINES OF perl_fragments INTO perl_string.
EXIT.
ENDIF.
ELSE.
ASSIGN abap_data TO .
ENDIF.
* Get ABAP data type again and start
DESCRIBE FIELD TYPE l_type COMPONENTS l_comps.
***************************************************
* Tables
***************************************************
IF l_type EQ cl_abap_typedescr=>typekind_table.
* '[' Table opening bracket
APPEND '[' TO perl_fragments.
ASSIGN TO .
l_lines = lines( ).
LOOP AT ASSIGNING .
ADD 1 TO l_index.
*> Recursive call here
rec_perl_string = abap2perl( abap_data = upcase = upcase ).
APPEND rec_perl_string TO perl_fragments.
CLEAR rec_perl_string.
IF l_index < l_lines.
APPEND c_comma TO perl_fragments.
ENDIF.
ENDLOOP.
APPEND ']' TO perl_fragments.
* ']' Table closing bracket
***************************************************
* Structures
***************************************************
ELSE .
IF l_comps IS NOT INITIAL.
* '{' Object opening curly brace
APPEND '{' TO perl_fragments .
l_typedescr ?= cl_abap_typedescr=>describe_by_data( ) .
LOOP AT l_typedescr->components ASSIGNING .
l_index = sy-tabix .
ASSIGN COMPONENT -name OF STRUCTURE TO .
l_name = -name.
** ABAP names are usually in caps, set upcase to avoid the conversion to lower case.
IF upcase NE 'X'.
TRANSLATE l_name TO LOWER CASE.
ENDIF.
DESCRIBE FIELD TYPE s_type.
IF s_type EQ cl_abap_typedescr=>typekind_table OR s_type EQ cl_abap_typedescr=>typekind_dref OR
s_type EQ cl_abap_typedescr=>typekind_struct1 OR s_type EQ cl_abap_typedescr=>typekind_struct2.
*> Recursive call for non-scalars:
rec_perl_string = abap2perl( abap_data = name = l_name upcase = upcase ).
ELSE.
IF s_type EQ cl_abap_typedescr=>typekind_oref OR s_type EQ cl_abap_typedescr=>typekind_iref.
rec_perl_string = '"REF UNSUPPORTED"'.
ELSE.
get_scalar_value rec_perl_string s_type.
ENDIF.
CONCATENATE c_quote l_name c_quote perl_hash_assign rec_perl_string INTO rec_perl_string.
ENDIF.
APPEND rec_perl_string TO perl_fragments.
CLEAR rec_perl_string.
IF l_index < l_comps.
APPEND c_comma TO perl_fragments.
ENDIF.
ENDLOOP.
APPEND '}' TO perl_fragments.
* '}' Object closing curly brace
****************************************************
* - Scalars - *
****************************************************
ELSE.
get_scalar_value l_value l_type.
APPEND l_value TO perl_fragments.
ENDIF.
* End of structure/scalar IF block.
***********************************
ENDIF.
* End of main IF block.
**********************
* Use a loop in older releases that don't support concatenate lines.
CONCATENATE LINES OF perl_fragments INTO perl_string.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>ABAP2XML
* +-------------------------------------------------------------------------------------------------+
* | [--->] ABAP_DATA TYPE DATA
* | [--->] NAME TYPE STRING(optional)
* | [--->] WITH_XML_HEADER TYPE ABAP_BOOL (default =ABAP_FALSE)
* | [--->] UPCASE TYPE XFELD(optional)
* | [--->] NAME_ATR TYPE STRING(optional)
* | [<-()] XML_STRING TYPE STRING
* +--------------------------------------------------------------------------------------
METHOD abap2xml.
*
*/ Look at method serialize_id for a new way of doing XML.
TYPE-POOLS: abap.
CONSTANTS:
xml_head TYPE string VALUE '',
item_atr TYPE string VALUE 'idx="#"'.
DATA:
xml_fragments TYPE TABLE OF string,
rec_xml_string TYPE string,
l_type TYPE c,
s_type TYPE c,
l_comps TYPE i,
l_value TYPE string,
t_string TYPE string,
l_item_atr TYPE string,
l_item_str TYPE string,
l_name TYPE string,
l_idx TYPE string,
l_typedescr TYPE REF TO cl_abap_structdescr,
l_linedescr TYPE REF TO cl_abap_datadescr,
l_tabledescr TYPE REF TO cl_abap_tabledescr.
FIELD-SYMBOLS:
TYPE any,
TYPE ANY TABLE,
TYPE ANY TABLE,
TYPE any,
TYPE abap_compdescr.
DEFINE get_scalar_value.
" &1 : assigned var
" &2 : abap data
" &3 : abap type
&1 = &2.
****************************************************
* Adapt some basic ABAP types (pending inclusion of all basic abap types?)
* Feel free to customize this for your needs
CASE &3.
* 1. ABAP numeric types
WHEN 'I'. " Integer
CONDENSE &1.
IF sign( &1 ) < 0.
SHIFT &1 BY 1 PLACES RIGHT CIRCULAR.
ENDIF.
WHEN 'F'. " Float
CONDENSE &1.
WHEN 'P'. " Packed number (used in quantities, for example)
CONDENSE &1.
IF sign( &1 ) < 0.
SHIFT &1 BY 1 PLACES RIGHT CIRCULAR.
ENDIF.
WHEN 'X'. " Hexadecimal
CONDENSE &1.
CONCATENATE '0x' &1 INTO &1.
* 2. ABAP char types
WHEN 'D'. " Date type
CONCATENATE &1(4) '-' &1+4(2) '-' &1+6(2) INTO &1.
WHEN 'T'. " Time representation
CONCATENATE &1(2) ':' &1+2(2) ':' &1+4(2) INTO &1.
WHEN 'N'. " Numeric text field
* condense &1.
WHEN 'C' OR 'g'. " Char sequences and Strings
* Put safe chars
t_string = &2.
&1 = cl_http_utility=>escape_html( t_string ).
WHEN 'y'. " XSTRING
* Put the XSTRING in Base64
&1 = cl_http_utility=>encode_x_base64( &2 ).
WHEN OTHERS.
* Don't hesitate to add and modify abap types to suit your taste.
ENDCASE.
** End of scalar data preparing.
end-of-definition.
*******************************
* Put XML header if requested *
*******************************
IF with_xml_header EQ abap_true.
APPEND xml_head TO xml_fragments.
ENDIF.
***************************************************
* Open XML tag *
* < > *
***************************************************
IF name IS NOT INITIAL.
l_name = name.
IF name_atr IS NOT INITIAL.
CONCATENATE name name_atr INTO l_name SEPARATED BY space.
ENDIF.
CONCATENATE '<' l_name '>' INTO rec_xml_string.
APPEND rec_xml_string TO xml_fragments.
CLEAR rec_xml_string.
ENDIF.
**
* Get ABAP data type
DESCRIBE FIELD abap_data TYPE l_type COMPONENTS l_comps .
***************************************************
* Get rid of data references
***************************************************
IF l_type EQ cl_abap_typedescr=>typekind_dref.
ASSIGN abap_data->* TO .
IF sy-subrc NE 0.
IF name IS NOT INITIAL.
CONCATENATE '<' name '/>' INTO xml_string.
ELSE.
CLEAR xml_string.
ENDIF.
EXIT.
ENDIF.
ELSE.
ASSIGN abap_data TO .
ENDIF.
* Get ABAP data type again and start
DESCRIBE FIELD TYPE l_type COMPONENTS l_comps.
***************************************************
* Tables
***************************************************
IF l_type EQ cl_abap_typedescr=>typekind_table.
l_tabledescr ?= cl_abap_typedescr=>describe_by_data( ).
l_linedescr = l_tabledescr->get_table_line_type( ).
l_item_str = l_linedescr->get_relative_name( ).
ASSIGN TO .
LOOP AT ASSIGNING .
l_idx = sy-tabix.
CONDENSE l_idx.
l_item_atr = item_atr.
REPLACE '#' IN l_item_atr WITH l_idx.
IF upcase NE 'X'.
TRANSLATE l_item_str TO LOWER CASE.
ENDIF.
*> Recursive call for line items here:
rec_xml_string = abap2xml( abap_data = upcase = upcase name = l_item_str name_atr = l_item_atr ).
APPEND rec_xml_string TO xml_fragments.
CLEAR rec_xml_string.
ENDLOOP.
***************************************************
* Structures
***************************************************
ELSE .
IF l_comps IS NOT INITIAL.
l_typedescr ?= cl_abap_typedescr=>describe_by_data( ).
LOOP AT l_typedescr->components ASSIGNING .
ASSIGN COMPONENT -name OF STRUCTURE TO .
l_name = -name. " l_value justs holds the name here.
** ABAP names are usually in caps, set upcase to avoid the conversion to lower case.
IF upcase NE 'X'.
TRANSLATE l_name TO LOWER CASE.
ENDIF.
DESCRIBE FIELD TYPE s_type.
IF s_type EQ cl_abap_typedescr=>typekind_table OR s_type EQ cl_abap_typedescr=>typekind_dref OR
s_type EQ cl_abap_typedescr=>typekind_struct1 OR s_type EQ cl_abap_typedescr=>typekind_struct2.
*> Recursive call for non-scalars:
rec_xml_string = abap2xml( abap_data = name = l_name upcase = upcase ).
ELSE.
IF s_type EQ cl_abap_typedescr=>typekind_oref OR s_type EQ cl_abap_typedescr=>typekind_iref.
rec_xml_string = 'REF UNSUPPORTED'.
ELSE.
get_scalar_value rec_xml_string s_type.
ENDIF.
CONCATENATE '<' l_name '>' rec_xml_string '' l_name '>' INTO rec_xml_string.
ENDIF.
APPEND rec_xml_string TO xml_fragments.
CLEAR rec_xml_string.
ENDLOOP.
****************************************************
* - Scalars - *
****************************************************
ELSE.
get_scalar_value l_value l_type.
APPEND l_value TO xml_fragments.
ENDIF.
* End of structure/scalar IF block.
***********************************
ENDIF.
* End of main IF block.
**********************
*****************
* Close XML tag *
*****************
IF name IS NOT INITIAL.
CONCATENATE '' name '>' INTO rec_xml_string.
APPEND rec_xml_string TO xml_fragments.
CLEAR rec_xml_string.
ENDIF.
* Use a loop in older releases that don't support concatenate lines.
CONCATENATE LINES OF xml_fragments INTO xml_string.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>ABAP2YAML
* +-------------------------------------------------------------------------------------------------+
* | [--->] ABAP_DATA TYPE DATA
* | [--->] NAME TYPE STRING(optional)
* | [--->] UPCASE TYPE XFELD(optional)
* | [--->] Y_LEVEL TYPE I (default =0)
* | [--->] S_INDEX TYPE I (default =0)
* | [--->] FIRST_ROW TYPE XFELD(optional)
* | [--->] DONT_INDENT TYPE XFELD(optional)
* | [<-()] YAML_STRING TYPE STRING
* | [EXC!] ERROR_IN_DATA_DESCRIPTION
* +--------------------------------------------------------------------------------------
METHOD abap2yaml.
*********************
* ABAP goes to YAML *
*********************
TYPE-POOLS: abap.
CONSTANTS:
c_comma TYPE c VALUE ',',
c_space TYPE c VALUE ' ',
c_colon TYPE c VALUE ':',
c_quote TYPE c VALUE '"',
c_squot TYPE c VALUE '''',
c_colo2(2) TYPE c VALUE ': ',
c_indt2 TYPE i VALUE 2,
c_hyph TYPE c VALUE '-'.
DATA:
ly_level TYPE i,
l_dont_indent TYPE xfeld,
dec_level TYPE i VALUE 0,
dont_quote TYPE xfeld,
yaml_fragments TYPE TABLE OF string,
rec_yaml_string TYPE string,
l_type TYPE c,
l_comps TYPE i,
l_lines TYPE i,
l_index TYPE i,
l_value TYPE string,
l_name TYPE string.
FIELD-SYMBOLS:
TYPE any,
TYPE ANY TABLE,
TYPE ANY TABLE,
TYPE any.
DATA l_typedescr TYPE REF TO cl_abap_structdescr .
FIELD-SYMBOLS TYPE abap_compdescr .
ly_level = y_level.
**
* Get ABAP data type
DESCRIBE FIELD abap_data TYPE l_type COMPONENTS l_comps .
***************************************************
* First of all, get rid of data references
***************************************************
IF l_type EQ cl_abap_typedescr=>typekind_dref.
ASSIGN abap_data->* TO .
IF sy-subrc NE 0.
yaml_string = space. " pasamos de poner nada si falla...
EXIT.
ENDIF.
ELSE.
ASSIGN abap_data TO .
ENDIF.
* Get ABAP data type again and start
DESCRIBE FIELD TYPE l_type COMPONENTS l_comps.
***************************************************
* Prepare field names, YAML does not quote names *
***************************************************
* Put hyphens...
IF name IS INITIAL AND y_level GT 0.
CONCATENATE c_hyph space INTO rec_yaml_string RESPECTING BLANKS.
l_dont_indent = 'X'.
ENDIF.
IF name IS NOT INITIAL.
CONCATENATE name c_colon c_space INTO rec_yaml_string RESPECTING BLANKS.
ENDIF.
* do indent
IF dont_indent NE 'X'.
DO ly_level TIMES.
SHIFT rec_yaml_string RIGHT BY c_indt2 PLACES.
ENDDO.
ENDIF.
APPEND rec_yaml_string TO yaml_fragments.
CLEAR rec_yaml_string.
***************************************************
* Tables
***************************************************
IF l_type EQ cl_abap_typedescr=>typekind_table.
ASSIGN TO .
l_lines = lines( ).
CLEAR l_index.
IF l_lines EQ 0.
MOVE '[]' TO rec_yaml_string.
APPEND rec_yaml_string TO yaml_fragments.
CLEAR rec_yaml_string.
APPEND xnl TO yaml_fragments.
ELSE.
IF name IS NOT INITIAL.
APPEND xnl TO yaml_fragments.
ENDIF.
ADD 1 TO ly_level.
LOOP AT ASSIGNING .
ADD 1 TO l_index.
*> Recursive call here
rec_yaml_string = abap2yaml( abap_data = upcase = upcase y_level = ly_level s_index = l_index ).
APPEND rec_yaml_string TO yaml_fragments.
CLEAR rec_yaml_string.
ENDLOOP.
ENDIF.
* YAML table ends *
*******************
***************************************************
* Structures
***************************************************
ELSE .
IF l_comps IS NOT INITIAL.
IF name IS NOT INITIAL.
APPEND xnl TO yaml_fragments.
ENDIF.
ADD 1 TO ly_level.
* Loop for structure elements
l_typedescr ?= cl_abap_typedescr=>describe_by_data( ) .
CLEAR l_index.
LOOP AT l_typedescr->components ASSIGNING .
ADD 1 TO l_index.
ASSIGN COMPONENT -name OF STRUCTURE TO .
l_name = -name.
** ABAP names are usually in caps, set upcase to avoid the conversion to lower case.
IF upcase NE 'X'.
TRANSLATE l_name TO LOWER CASE.
ENDIF.
*> Recursive call here
rec_yaml_string = abap2yaml( abap_data = name = l_name upcase = upcase y_level = ly_level s_index = l_index dont_indent = l_dont_indent ).
CLEAR l_dont_indent. " it is only used once
APPEND rec_yaml_string TO yaml_fragments.
CLEAR rec_yaml_string.
ENDLOOP.
* YAML structure ends *
***********************
***************************************************
* Scalars and others...
***************************************************
ELSE.
IF l_type EQ cl_abap_typedescr=>typekind_oref OR l_type EQ cl_abap_typedescr=>typekind_iref.
l_value = 'REF UNSUPPORTED'.
ELSE.
l_value = .
ENDIF.
* Adapt some basic ABAP types (pending inclusion of all basic abap types)
* Feel free to customize this for your needs
CASE l_type.
* 1. ABAP numeric types
WHEN 'I'. " Integer
CONDENSE l_value.
IF sign( l_value ) < 0.
SHIFT l_value BY 1 PLACES RIGHT CIRCULAR.
ENDIF.
dont_quote = 'X'.
WHEN 'F'. " Float
CONDENSE l_value.
dont_quote = 'X'.
WHEN 'P'. " Packed number (used in quantities, for example)
CONDENSE l_value.
IF sign( l_value ) < 0.
SHIFT l_value BY 1 PLACES RIGHT CIRCULAR.
ENDIF.
dont_quote = 'X'.
WHEN 'X'. " Hexadecimal
CONDENSE l_value.
CONCATENATE '0x' l_value INTO l_value.
dont_quote = 'X'.
* 2. ABAP char types
WHEN 'D'. " Date type
CONCATENATE l_value(4) '-' l_value+4(2) '-' l_value+6(2) INTO l_value.
WHEN 'T'. " Time representation
CONCATENATE l_value(2) ':' l_value+2(2) ':' l_value+4(2) INTO l_value.
WHEN 'N'. " Numeric text field
* condense l_value.
WHEN 'C' OR 'g'. " Chars and Strings
* Put safe chars
REPLACE ALL OCCURRENCES OF '\' IN l_value WITH '\\' .
REPLACE ALL OCCURRENCES OF '"' IN l_value WITH '\"' .
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>cr_lf IN l_value WITH '\r\n' .
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>newline IN l_value WITH '\n' .
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>horizontal_tab IN l_value WITH '\t' .
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>backspace IN l_value WITH '\b' .
REPLACE ALL OCCURRENCES OF cl_abap_char_utilities=>form_feed IN l_value WITH '\f' .
WHEN 'y'. " XSTRING
* Put the XSTRING in Base64
* l_value = cl_http_utility=>ENCODE_X_BASE64( ).
l_value = 'XSTRING not supported in YAML yet!'.
WHEN OTHERS.
* Don't hesitate to add and modify abap types to suit your taste.
ENDCASE.
* We use YAML scalars double quoted
IF dont_quote NE 'X'.
CONCATENATE c_quote l_value c_quote INTO l_value.
ELSE.
CLEAR dont_quote.
ENDIF.
APPEND l_value TO yaml_fragments.
APPEND xnl TO yaml_fragments.
ENDIF. " is structure or scalar
ENDIF. " main typekind sentence
* Use a loop in older releases that don't support concatenate lines.
CONCATENATE LINES OF yaml_fragments INTO yaml_string RESPECTING BLANKS.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>BUILD_PARAMS
* +-------------------------------------------------------------------------------------------------+
* | [--->] FUNCTION_NAME TYPE RS38L_FNAM
* | [<---] PARAMTAB TYPE ABAP_FUNC_PARMBIND_TAB
* | [<---] EXCEPTAB TYPE ABAP_FUNC_EXCPBIND_TAB
* | [<---] PARAMS TYPE ANY
* | [EXC!] INVALID_FUNCTION
* | [EXC!] UNSUPPORTED_PARAM_TYPE
* +--------------------------------------------------------------------------------------
METHOD build_params.
TYPE-POOLS: abap.
DATA defval TYPE rs38l_defo.
DATA dataname TYPE string.
DATA waref TYPE REF TO data.
FIELD-SYMBOLS:
TYPE any,
TYPE any.
DATA len TYPE i.
DATA excnt TYPE i VALUE 1.
DATA paramline TYPE LINE OF abap_func_parmbind_tab.
DATA exceptline TYPE LINE OF abap_func_excpbind_tab.
DATA t_params_p TYPE TABLE OF rfc_fint_p.
DATA params_p TYPE rfc_fint_p.
DEFINE remove_enclosing_quotes.
" Remove enclosing single quotes
IF &2 GT 1.
SUBTRACT 1 FROM &2.
IF &1+&2 EQ ''''.
&1+&2 = space.
ENDIF.
IF &1(1) EQ ''''.
SHIFT &1 LEFT.
ENDIF.
&2 = strlen( &1 ).
ENDIF.
end-of-definition.
* do we have the rfc name?
CALL FUNCTION 'RFC_GET_FUNCTION_INTERFACE_P'
EXPORTING
funcname = function_name
language = 'E' "'D' "sy-langu
TABLES
params_p = t_params_p
EXCEPTIONS
fu_not_found = 1
nametab_fault = 2
OTHERS = 3.
IF sy-subrc <> 0.
RAISE invalid_function.
ENDIF.
* Build params table
LOOP AT t_params_p INTO params_p.
UNASSIGN .
UNASSIGN .
CLEAR paramline.
CASE params_p-paramclass.
WHEN 'I' OR 'E' OR 'C'.
paramline-name = params_p-parameter.
IF params_p-paramclass = 'E'.
paramline-kind = abap_func_importing.
ELSEIF params_p-paramclass = 'I'.
paramline-kind = abap_func_exporting.
ELSE.
paramline-kind = abap_func_changing.
ENDIF.
IF params_p-fieldname IS INITIAL.
dataname = params_p-tabname.
ELSE.
CONCATENATE params_p-tabname params_p-fieldname INTO
dataname SEPARATED BY '-'.
ENDIF.
* Assign default values
defval = params_p-default.
IF dataname IS INITIAL.
dataname = 'STRING'. " use a STRING for this cases (see CONVERT_DATE_TO_EXTERNAL).
ENDIF.
CREATE DATA waref TYPE (dataname).
ASSIGN waref->* TO .
len = strlen( defval ).
remove_enclosing_quotes defval len.
IF defval = 'SPACE'.
= space.
ELSEIF len > 3 AND defval+0(3) = 'SY-'.
ASSIGN (defval) TO .
= .
UNASSIGN .
ELSE.
IF defval IS NOT INITIAL.
= defval.
ENDIF.
ENDIF.
UNASSIGN .
paramline-value = waref.
INSERT paramline INTO TABLE paramtab.
WHEN 'T'.
paramline-name = params_p-parameter.
paramline-kind = abap_func_tables.
IF params_p-exid EQ 'h'.
CREATE DATA waref TYPE (params_p-tabname).
ELSE.
CREATE DATA waref TYPE STANDARD TABLE OF (params_p-tabname).
ENDIF.
paramline-value = waref.
INSERT paramline INTO TABLE paramtab.
WHEN 'X'.
exceptline-name = params_p-parameter.
exceptline-value = excnt.
DATA messg TYPE REF TO data.
CREATE DATA messg TYPE string.
ASSIGN messg->* TO .
= params_p-paramtext.
exceptline-message = messg.
INSERT exceptline INTO TABLE exceptab.
ADD 1 TO excnt.
WHEN OTHERS.
RAISE unsupported_param_type.
ENDCASE.
ENDLOOP.
* add in the catch all exception
exceptline-name = 'OTHERS'.
exceptline-value = excnt.
INSERT exceptline INTO TABLE exceptab.
* return
params = t_params_p.
*********************************
******* Remaining from 2006 *****
******* end of build_params *****
*********************************
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>CONVERT_JSON_DATETIME_TO_ABAP
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_TIMESTAMP TYPE STRING
* | [<---] EV_DATE TYPE SYDATE
* | [<---] EV_TIME TYPE SYUZEIT
* | [<---] EV_MSEC TYPE NUM03
* +--------------------------------------------------------------------------------------
METHOD convert_json_datetime_to_abap.
DATA:
lv_date TYPE sy-datum,
lv_days_i TYPE i,
lv_sec_i TYPE i,
lv_timestamp TYPE timestampl,
lv_timsmsec TYPE timestampl.
CONSTANTS:
lc_day_in_sec TYPE i VALUE 86400.
CHECK iv_timestamp IS NOT INITIAL.
* IV_TIMESTAMP stores milliseconds since January 1, 1970, 00:00:00 GMT
lv_timestamp = iv_timestamp / 1000. "timestamp in seconds
* One day has 86400 seconds: Timestamp in days
lv_days_i = lv_timestamp DIV lc_day_in_sec.
lv_date = '19700101'.
ev_date = lv_date + lv_days_i.
* Rest seconds (timestamp - days)
lv_sec_i = lv_timestamp MOD lc_day_in_sec.
ev_time = lv_sec_i.
* Rest sec and milli seconds
lv_timsmsec = lv_timestamp MOD lc_day_in_sec.
lv_timsmsec = lv_timsmsec - lv_sec_i.
ev_msec = lv_timsmsec * 1000.
* 转换为用户时区时间
DATA:lv_tstp TYPE timestamp,
lv_zone TYPE sy-zonlo VALUE 'UTC'.
CONVERT DATE ev_date TIME ev_time INTO TIME STAMP lv_tstp TIME ZONE lv_zone .
CONVERT TIME STAMP lv_tstp TIME ZONE sy-zonlo
INTO DATE ev_date TIME ev_time.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>DESERIALIZE_ID
* +-------------------------------------------------------------------------------------------------+
* | [--->] JSON TYPE STRING
* | [<-->] PARAMTAB TYPE ABAP_FUNC_PARMBIND_TAB
* | [!CX!] ZCX_JSON
* +--------------------------------------------------------------------------------------
METHOD deserialize_id.
*/***********************************************************/*
*/ New method using the built-in transformation /*
*/ included in releases 7.02 and 7.03/7.31 (Kernelpatch 116) /*
*/***********************************************************/*
TYPE-POOLS: abap.
** Remember function parameter types
**constants:
** abap_func_exporting type abap_func_parmbind-kind value 10,
** abap_func_importing type abap_func_parmbind-kind value 20,
** abap_func_tables type abap_func_parmbind-kind value 30,
** abap_func_changing type abap_func_parmbind-kind value 40.
DATA:
rtab TYPE abap_trans_resbind_tab,
rlin TYPE abap_trans_resbind,
oexcp TYPE REF TO cx_root,
etext TYPE string,
json_xtext TYPE xstring.
FIELD-SYMBOLS TYPE abap_func_parmbind.
IF json IS INITIAL. EXIT. ENDIF. " exit method if there is nothing to parse
" build rtab table for transformation id
LOOP AT paramtab ASSIGNING .
IF -kind EQ abap_func_importing. "" va al revés, cuidado!!!
CONTINUE.
ENDIF.
rlin-name = -name.
rlin-value = -value.
APPEND rlin TO rtab.
ENDLOOP.
" Convert input JSON variable names to uppercase
DATA: reader TYPE REF TO if_sxml_reader,
writer TYPE REF TO if_sxml_writer,
writer_str TYPE REF TO cl_sxml_string_writer,
node TYPE REF TO if_sxml_node,
open_element TYPE REF TO if_sxml_open_element,
attributes TYPE if_sxml_attribute=>attributes.
FIELD-SYMBOLS TYPE LINE OF if_sxml_attribute=>attributes.
json_xtext = cl_abap_codepage=>convert_to( json ).
reader = cl_sxml_string_reader=>create( json_xtext ).
writer ?= cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
DO.
node = reader->read_next_node( ).
IF node IS INITIAL.
EXIT.
ENDIF.
IF node->type = if_sxml_node=>co_nt_element_open.
open_element ?= node.
attributes = open_element->get_attributes( ).
LOOP AT attributes ASSIGNING .
IF ->qname-name = 'name'.
->set_value(
to_upper( ->get_value( ) ) ).
ENDIF.
ENDLOOP.
ENDIF.
writer->write_node( node ).
ENDDO.
writer_str ?= writer.
json_xtext = writer_str->get_output( ) .
TRY.
CALL TRANSFORMATION id SOURCE XML json_xtext
RESULT (rtab).
CATCH cx_root INTO oexcp.
etext = oexcp->if_message~get_text( ).
RAISE EXCEPTION TYPE zcx_json
EXPORTING
message = etext.
ENDTRY.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>JSON2ABAP
* +-------------------------------------------------------------------------------------------------+
* | [--->] JSON_STRING TYPE STRING(optional)
* | [--->] VAR_NAME TYPE STRING(optional)
* | [--->] PROPERTY_PATH TYPE STRING (default ='json_obj')
* | [<---] PROPERTY_TABLE TYPE JS_PROPERTY_TAB
* | [<-->] JS_OBJECT TYPE REF TO CL_JAVA_SCRIPT
* | [<-->] ABAP_DATA TYPE ANY(optional)
* | [!CX!] ZCX_JSON
* +--------------------------------------------------------------------------------------
METHOD json2abap.
*/************************************************/*
*/ Input any abap data and this method tries to /*
*/ fill it with the data in the JSON string. /*
*/ Thanks to Juan Diaz for helping here!! /*
*/************************************************/*
TYPE-POOLS: abap, js.
DATA:
js_script TYPE string,
js_started TYPE i VALUE 0,
l_json_string TYPE string,
js_property_table TYPE js_property_tab,
js_property TYPE LINE OF js_property_tab,
l_property_path TYPE string,
compname TYPE string,
item_path TYPE string.
DATA:
l_type TYPE c,
l_value TYPE string,
linetype TYPE string,
l_comp TYPE LINE OF abap_compdescr_tab.
DATA:
datadesc TYPE REF TO cl_abap_typedescr,
drefdesc TYPE REF TO cl_abap_typedescr,
linedesc TYPE REF TO cl_abap_typedescr,
strudesc TYPE REF TO cl_abap_structdescr,
tabldesc TYPE REF TO cl_abap_tabledescr.
DATA newline TYPE REF TO data.
FIELD-SYMBOLS:
TYPE any,
TYPE ANY TABLE,
TYPE any,
TYPE LINE OF js_property_tab,
TYPE abap_compdescr.
DEFINE assign_scalar_value.
" &1
" &2 js_property-value
DESCRIBE FIELD &1 TYPE l_type.
l_value = &2.
* convert or adapt scalar values to ABAP.
CASE l_type.
WHEN 'D'. " date type
IF l_value CS '-'.
REPLACE ALL OCCURRENCES OF '-' IN l_value WITH space.
CONDENSE l_value NO-GAPS.
ENDIF.
WHEN 'T'. " time type
IF l_value CS ':'.
REPLACE ALL OCCURRENCES OF ':' IN l_value WITH space.
CONDENSE l_value NO-GAPS.
ENDIF.
WHEN OTHERS.
" may be other conversions or checks could be implemented here.
ENDCASE.
&1 = l_value.
end-of-definition.
IF js_object IS NOT BOUND.
IF json_string IS INITIAL. EXIT. ENDIF. " exit method if there is nothing to parse
l_json_string = json_string.
" js_object = cl_java_script=>create( STACKSIZE = 16384 ).
js_object = cl_java_script=>create( stacksize = 16384 heapsize = 960000 ).
***************************************************
* Parse JSON using JavaScript *
***************************************************
js_object->bind( EXPORTING name_obj = 'abap_data' name_prop = 'json_string' CHANGING data = l_json_string ).
js_object->bind( EXPORTING name_obj = 'abap_data' name_prop = 'script_started' CHANGING data = js_started ).
* We use the JavaScript engine included in ABAP to read the JSON string.
* We simply use the recommended way to eval a JSON string as specified
* in RFC 4627 (http://www.ietf.org/rfc/rfc4627.txt).
*
* Security considerations:
*
* Generally there are security issues with scripting languages. JSON
* is a subset of JavaScript, but it is a safe subset that excludes
* assignment and invocation.
*
* A JSON text can be safely passed into JavaScript's eval() function
* (which compiles and executes a string) if all the characters not
* enclosed in strings are in the set of characters that form JSON
* tokens. This can be quickly determined in JavaScript with two
* regular expressions and calls to the test and replace methods.
*
* var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
* text.replace(/"(\\.|[^"\\])*"/g, ''))) &&
* eval('(' + text + ')');
CONCATENATE
'var json_obj; '
'var json_text; '
'function start() { '
' if(abap_data.script_started) { return; } '
' json_text = abap_data.json_string;'
' json_obj = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( '
' json_text.replace(/"(\\.|[^"\\])*"/g, ''''))) && '
' eval(''('' + json_text + '')''); '
' abap_data.script_started = 1; '
'} '
'if(!abap_data.script_started) start(); '
INTO js_script RESPECTING BLANKS SEPARATED BY xnl.
js_object->compile( script_name = 'json_parser' script = js_script ).
js_object->execute( script_name = 'json_parser' ).
IF js_object->last_error_message IS NOT INITIAL.
RAISE EXCEPTION TYPE zcx_json
EXPORTING
message = js_object->last_error_message.
ENDIF.
ENDIF.
** End of JS processing.
**
IF var_name IS NOT INITIAL.
CONCATENATE property_path var_name INTO l_property_path SEPARATED BY '.'.
ELSE.
l_property_path = property_path.
ENDIF.
**
**
js_property_table = js_object->get_properties_scope_global( property_path = l_property_path ).
property_table = js_property_table.
* Exit if abap_data is not supplied, normally when called
* from json_deserialize to get top level properties
IF abap_data IS NOT SUPPLIED.
EXIT.
ENDIF. "***
*
* Get ABAP data type, dereference if necessary and start
datadesc = cl_abap_typedescr=>describe_by_data( abap_data ).
IF datadesc->kind EQ cl_abap_typedescr=>kind_ref.
ASSIGN abap_data->* TO .
ELSE.
ASSIGN abap_data TO .
ENDIF.
datadesc = cl_abap_typedescr=>describe_by_data( ).
CASE datadesc->kind.
WHEN cl_abap_typedescr=>kind_elem.
* Scalar: process ABAP elements. Assume no type conversions for the moment.
IF var_name IS INITIAL.
RAISE EXCEPTION TYPE zcx_json
EXPORTING
message = 'VAR_NAME is required for scalar values.'.
ENDIF.
js_property_table = js_object->get_properties_scope_global( property_path = property_path ).
READ TABLE js_property_table WITH KEY name = var_name INTO js_property.
IF sy-subrc EQ 0.
assign_scalar_value js_property-value.
ENDIF.
WHEN cl_abap_typedescr=>kind_struct.
* Process ABAP structures
strudesc ?= datadesc.
LOOP AT js_property_table ASSIGNING .
compname = -name.
TRANSLATE compname TO UPPER CASE.
READ TABLE strudesc->components WITH KEY name = compname INTO l_comp.
IF sy-subrc EQ 0.
ASSIGN COMPONENT l_comp-name OF STRUCTURE TO .
CASE l_comp-type_kind.
WHEN cl_abap_typedescr=>typekind_struct1 " 'v'
OR cl_abap_typedescr=>typekind_struct2 " 'u'
OR cl_abap_typedescr=>typekind_table. " 'h' (may need a different treatment one day)
CONCATENATE l_property_path -name INTO item_path SEPARATED BY '.'.
*> Recursive call here
json2abap( EXPORTING property_path = item_path CHANGING abap_data = js_object = js_object ).
WHEN OTHERS.
* Process scalars in structures (same as the kind_elem above)
assign_scalar_value -value.
ENDCASE.
ENDIF.
ENDLOOP.
WHEN cl_abap_typedescr=>kind_table.
* Process ABAP tables
IF js_property_table IS NOT INITIAL.
tabldesc ?= datadesc.
linedesc = tabldesc->get_table_line_type( ).
linetype = linedesc->get_relative_name( ).
ASSIGN TO .
LOOP AT js_property_table INTO js_property WHERE name NE 'length'. " the JS object length
CREATE DATA newline TYPE (linetype).
ASSIGN newline->* TO .
CASE js_property-kind.
WHEN 'O'.
CONCATENATE l_property_path js_property-name INTO item_path SEPARATED BY '.'.
CONDENSE item_path.
*> Recursive call here
json2abap( EXPORTING property_path = item_path CHANGING abap_data = newline js_object = js_object ).
WHEN OTHERS. " Assume scalars, 'S', 'I', or other JS types
" Process scalars in plain table components(same as the kind_elem above)
assign_scalar_value js_property-value.
ENDCASE.
INSERT INTO TABLE .
FREE newline.
ENDLOOP.
ENDIF.
WHEN OTHERS. " kind_class, kind_intf
" forget it.
ENDCASE.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>JSON_DESERIALIZE
* +-------------------------------------------------------------------------------------------------+
* | [--->] JSON TYPE STRING
* | [<-->] PARAMTAB TYPE ABAP_FUNC_PARMBIND_TAB
* | [EXC!] ZCX_JSON
* +--------------------------------------------------------------------------------------
METHOD json_deserialize.
TYPE-POOLS: abap, js.
** Remember function parameter types
**constants:
** abap_func_exporting type abap_func_parmbind-kind value 10,
** abap_func_importing type abap_func_parmbind-kind value 20,
** abap_func_tables type abap_func_parmbind-kind value 30,
** abap_func_changing type abap_func_parmbind-kind value 40.
DATA paramname TYPE string.
DATA js_obj TYPE REF TO cl_java_script.
DATA js_prop_tab TYPE js_property_tab.
FIELD-SYMBOLS TYPE LINE OF js_property_tab.
FIELD-SYMBOLS TYPE abap_func_parmbind.
IF json IS INITIAL. EXIT. ENDIF.
json2abap( EXPORTING json_string = json IMPORTING property_table = js_prop_tab CHANGING js_object = js_obj ).
LOOP AT js_prop_tab ASSIGNING .
paramname = -name.
TRANSLATE paramname TO UPPER CASE.
READ TABLE paramtab WITH KEY name = paramname ASSIGNING .
IF sy-subrc EQ 0.
IF -kind NE abap_func_importing. "" va al revés, cuidado!!!
json2abap( EXPORTING var_name = -name CHANGING abap_data = -value js_object = js_obj ).
ENDIF.
ENDIF.
ENDLOOP.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_JSON_HANDLER->NOTES
* +-------------------------------------------------------------------------------------------------+
* | [<-()] TEXT TYPE STRING
* +--------------------------------------------------------------------------------------
METHOD notes.
DATA location TYPE string.
CONCATENATE me->my_url me->my_service '/RFC_SYSTEM_INFO' INTO location.
CONCATENATE
'JSON (NEW) handler notes '
'About this service...
'
'This is the ABAP implementation of a conversion program that'
' tranforms ABAP data into a JSON representation.'
''
'It provides a user interface in the form of a ICF service that '
'allows web invocation of ABAP function modules. It doesn''t matter if they are RFC enabled or not.'
'
In this system this service has '
'been assigned to ICF service ' me->my_service '.'
'
'
'In order to invoke a function module, just put its name in the PATH_INFO '
'of the service URL, as is shown in the following examples.'
'
Try the following link to do the default call in JSON format:
'
location
'?format=json
'
'A simple syntax allows to get the output in different formats.
'
'The following gets the output in YAML format:'
'
'
location
'?format=yaml
'
''
'And this will get the output in a basic XML representation:
'
location
'?format=xml
'
'And, just for fun, getting it into Perl format could be handy:
'
location
'?format=perl
'
'Finnally, you can add a callback to get the JSON response enclosed in a javascript function call,'
' in order to allow a JSONP style response: '
'
'
location '?format=json&callback=callMe
'
'
WARNING
This is work in progress and may not be suitable for use in productive '
'systems. The interface is somewhat unstable. Please feel free to test it and report '
'any bug and improvement you may find.'
'Use it at your own risk!'
'
For more information: '
'https://cw.sdn.sap.com/cw/groups/json-adapter-for-abap-function-modules'
'
'
'If you have any questions, please contact me at '
'[email protected]'
'
'
'
'
INTO text RESPECTING BLANKS.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>SERIALIZE_ID
* +-------------------------------------------------------------------------------------------------+
* | [--->] PARAMTAB TYPE ABAP_FUNC_PARMBIND_TAB
* | [--->] PARAMS TYPE ANY(optional)
* | [--->] EXCEPTAB TYPE ABAP_FUNC_EXCPBIND_TAB(optional)
* | [--->] SHOW_IMPP TYPE ABAP_BOOL(optional)
* | [--->] JSONP TYPE STRING(optional)
* | [--->] LOWERCASE TYPE ABAP_BOOL (default =ABAP_FALSE)
* | [--->] FORMAT TYPE STRING (default ='JSON')
* | [--->] FUNCNAME TYPE RS38L_FNAM(optional)
* | [--->] CAMELCASE TYPE ABAP_BOOL (default =ABAP_FALSE)
* | [<---] O_STRING TYPE STRING
* | [!CX!] ZCX_JSON
* +--------------------------------------------------------------------------------------
METHOD serialize_id.
*/***********************************************************/*
*/ New method using the built-in transformation /*
*/ included in releases 7.02 and 7.03/7.31 (Kernelpatch 116) /*
*/ Generates both JSON and XML formats!!
*/***********************************************************/*
*/
** Remember function parameter types
**constants:
** abap_func_exporting type abap_func_parmbind-kind value 10,
** abap_func_importing type abap_func_parmbind-kind value 20,
** abap_func_tables type abap_func_parmbind-kind value 30,
** abap_func_changing type abap_func_parmbind-kind value 40.
TYPE-POOLS: abap.
DATA:
stab TYPE abap_trans_srcbind_tab,
slin TYPE abap_trans_srcbind,
oexcp TYPE REF TO cx_root,
etext TYPE string,
adata TYPE REF TO data,
json_writer TYPE REF TO cl_sxml_string_writer.
FIELD-SYMBOLS TYPE abap_func_parmbind.
* field-symbols type abap_func_excpbind.
LOOP AT paramtab ASSIGNING .
IF show_impp NE 'X'
AND -kind EQ abap_func_exporting. "" va al revés, cuidado!!!
CONTINUE.
ENDIF.
slin-name = -name.
slin-value = -value.
APPEND slin TO stab. CLEAR slin.
ENDLOOP.
IF exceptab IS NOT INITIAL.
slin-name = 'EXCEPTION'.
GET REFERENCE OF exceptab INTO adata.
slin-value = adata.
APPEND slin TO stab. CLEAR slin.
ENDIF.
json_writer = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
TRY.
CASE format.
WHEN 'XML'.
CALL TRANSFORMATION id OPTIONS data_refs = 'embedded'
initial_components = 'include'
SOURCE (stab)
RESULT XML o_string.
WHEN OTHERS.
CALL TRANSFORMATION id OPTIONS data_refs = 'embedded'
initial_components = 'include'
SOURCE (stab)
RESULT XML json_writer.
o_string = cl_abap_codepage=>convert_from( json_writer->get_output( ) ).
* json_string = json_writer->get_output( ).
IF jsonp IS NOT INITIAL.
CONCATENATE jsonp '(' o_string ');' INTO o_string.
ENDIF.
ENDCASE.
CATCH cx_root INTO oexcp.
etext = oexcp->if_message~get_text( ).
RAISE EXCEPTION TYPE zcx_json
EXPORTING
message = etext.
ENDTRY.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>SERIALIZE_JSON
* +-------------------------------------------------------------------------------------------------+
* | [--->] PARAMTAB TYPE ABAP_FUNC_PARMBIND_TAB
* | [--->] PARAMS TYPE ANY(optional)
* | [--->] EXCEPTAB TYPE ABAP_FUNC_EXCPBIND_TAB(optional)
* | [--->] SHOW_IMPP TYPE ABAP_BOOL(optional)
* | [--->] JSONP TYPE STRING(optional)
* | [--->] LOWERCASE TYPE ABAP_BOOL (default =ABAP_FALSE)
* | [--->] CAMELCASE TYPE ABAP_BOOL (default =ABAP_FALSE)
* | [<---] O_STRING TYPE STRING
* +--------------------------------------------------------------------------------------
METHOD serialize_json.
* ABAP based JSON serializer for function modules (January 2013).
TYPE-POOLS: abap.
** Remember function parameter types
**constants:
** abap_func_exporting type abap_func_parmbind-kind value 10,
** abap_func_importing type abap_func_parmbind-kind value 20,
** abap_func_tables type abap_func_parmbind-kind value 30,
** abap_func_changing type abap_func_parmbind-kind value 40.
DATA json_fragments TYPE TABLE OF string.
DATA rec_json_string TYPE string.
DATA paramname TYPE string.
DATA l_lines TYPE i.
DATA l_index TYPE i.
DATA upcase TYPE xfeld VALUE 'X'.
FIELD-SYMBOLS TYPE abap_func_parmbind.
FIELD-SYMBOLS TYPE abap_func_excpbind.
IF jsonp IS NOT INITIAL.
APPEND jsonp TO json_fragments.
APPEND '(' TO json_fragments.
ENDIF.
rec_json_string = '{'.
APPEND rec_json_string TO json_fragments.
CLEAR rec_json_string.
CLEAR l_index.
l_lines = lines( paramtab ).
LOOP AT paramtab ASSIGNING .
IF show_impp NE 'X'
AND -kind EQ abap_func_exporting. "" va al revés, cuidado!!!
SUBTRACT 1 FROM l_lines.
CONTINUE.
ENDIF.
ADD 1 TO l_index.
paramname = -name.
IF lowercase EQ abap_true.
TRANSLATE paramname TO LOWER CASE.
" paramname = to_lower( paramname ).
upcase = space.
ENDIF.
IF camelcase EQ abap_true.
paramname = to_mixed( val = paramname case = 'a').
ENDIF.
rec_json_string = abap2json( abap_data = -value name = paramname upcase = upcase camelcase = camelcase ).
APPEND rec_json_string TO json_fragments.
CLEAR rec_json_string.
IF l_index < l_lines.
APPEND ',' TO json_fragments .
ENDIF .
ENDLOOP.
IF exceptab IS NOT INITIAL.
IF l_lines GT 0.
APPEND ',' TO json_fragments.
ENDIF.
rec_json_string = abap2json( abap_data = exceptab upcase = 'X' name = 'EXCEPTION').
APPEND rec_json_string TO json_fragments.
CLEAR rec_json_string.
ENDIF.
rec_json_string = '}'.
APPEND rec_json_string TO json_fragments.
CLEAR rec_json_string.
IF jsonp IS NOT INITIAL.
APPEND ');' TO json_fragments.
ENDIF.
CONCATENATE LINES OF json_fragments INTO o_string.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>SERIALIZE_PERL
* +-------------------------------------------------------------------------------------------------+
* | [--->] PARAMTAB TYPE ABAP_FUNC_PARMBIND_TAB
* | [--->] PARAMS TYPE ANY(optional)
* | [--->] EXCEPTAB TYPE ABAP_FUNC_EXCPBIND_TAB(optional)
* | [--->] SHOW_IMPP TYPE ABAP_BOOL(optional)
* | [--->] JSONP TYPE STRING(optional)
* | [--->] LOWERCASE TYPE ABAP_BOOL (default =ABAP_FALSE)
* | [--->] FUNCNAME TYPE RS38L_FNAM
* | [<---] PERL_STRING TYPE STRING
* +--------------------------------------------------------------------------------------
METHOD serialize_perl.
* Just for fun, generate data in Perl Data::Dumper format.
TYPE-POOLS: abap.
**Remember function parameter types
**constants:
** abap_func_exporting type abap_func_parmbind-kind value 10,
** abap_func_importing type abap_func_parmbind-kind value 20,
** abap_func_tables type abap_func_parmbind-kind value 30,
** abap_func_changing type abap_func_parmbind-kind value 40.
DATA perl_fragments TYPE TABLE OF string.
DATA rec_perl_string TYPE string.
DATA paramname TYPE string.
DATA l_lines TYPE i.
DATA l_index TYPE i.
DATA upcase TYPE xfeld VALUE 'X'.
DATA perl_var TYPE string.
FIELD-SYMBOLS TYPE abap_func_parmbind.
FIELD-SYMBOLS TYPE abap_func_excpbind.
IF jsonp IS NOT INITIAL.
perl_var = jsonp.
ELSE.
perl_var = funcname.
ENDIF.
CONCATENATE '$' perl_var ' = {' INTO rec_perl_string.
APPEND rec_perl_string TO perl_fragments.
CLEAR rec_perl_string.
CLEAR l_index.
l_lines = lines( paramtab ).
LOOP AT paramtab ASSIGNING .
IF show_impp NE 'X'
AND -kind EQ abap_func_exporting. "" va al revés, cuidado!!!
SUBTRACT 1 FROM l_lines.
CONTINUE.
ENDIF.
ADD 1 TO l_index.
paramname = -name.
IF lowercase EQ abap_true.
TRANSLATE paramname TO LOWER CASE.
upcase = space.
ENDIF.
rec_perl_string = abap2perl( abap_data = -value name = paramname upcase = upcase ).
APPEND rec_perl_string TO perl_fragments.
CLEAR rec_perl_string.
IF l_index < l_lines.
APPEND ',' TO perl_fragments .
ENDIF .
ENDLOOP.
IF exceptab IS NOT INITIAL.
IF l_lines GT 0.
APPEND ',' TO perl_fragments.
ENDIF.
rec_perl_string = abap2perl( abap_data = exceptab upcase = 'X' name = 'EXCEPTION').
APPEND rec_perl_string TO perl_fragments.
CLEAR rec_perl_string.
ENDIF.
rec_perl_string = '};'.
APPEND rec_perl_string TO perl_fragments.
CLEAR rec_perl_string.
CONCATENATE LINES OF perl_fragments INTO perl_string.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>SERIALIZE_XML
* +-------------------------------------------------------------------------------------------------+
* | [--->] PARAMTAB TYPE ABAP_FUNC_PARMBIND_TAB
* | [--->] PARAMS TYPE ANY(optional)
* | [--->] EXCEPTAB TYPE ABAP_FUNC_EXCPBIND_TAB(optional)
* | [--->] SHOW_IMPP TYPE ABAP_BOOL(optional)
* | [--->] JSONP TYPE STRING(optional)
* | [--->] FUNCNAME TYPE RS38L_FNAM
* | [--->] LOWERCASE TYPE ABAP_BOOL (default =ABAP_FALSE)
* | [--->] FORMAT TYPE STRING
* | [<---] O_STRING TYPE STRING
* +--------------------------------------------------------------------------------------
METHOD serialize_xml.
* Serialize function data into simple XML
*/ Look at method serialize_id for a new way of doing XML.
TYPE-POOLS: abap.
** Remember function parameter types
***constants:
*** abap_func_exporting type abap_func_parmbind-kind value 10,
*** abap_func_importing type abap_func_parmbind-kind value 20,
*** abap_func_tables type abap_func_parmbind-kind value 30,
*** abap_func_changing type abap_func_parmbind-kind value 40.
DATA rec_xml_string TYPE string.
DATA xml_fragments TYPE TABLE OF string.
DATA l_funcname TYPE string.
DATA paramname TYPE string.
FIELD-SYMBOLS TYPE abap_func_parmbind.
FIELD-SYMBOLS TYPE abap_func_excpbind.
DATA upcase TYPE xfeld VALUE 'X'.
CONSTANTS:
xml_head TYPE string VALUE ''.
APPEND xml_head TO xml_fragments.
l_funcname = funcname.
IF lowercase EQ abap_true.
TRANSLATE l_funcname TO LOWER CASE.
upcase = space.
ENDIF.
CONCATENATE '<' l_funcname '>' INTO rec_xml_string.
APPEND rec_xml_string TO xml_fragments.
LOOP AT paramtab ASSIGNING .
IF show_impp NE 'X'
AND -kind EQ abap_func_exporting. "" va al revés, cuidado!!!
CONTINUE.
ENDIF.
paramname = -name.
IF lowercase EQ abap_true.
TRANSLATE paramname TO LOWER CASE.
ENDIF.
rec_xml_string = abap2xml( name = paramname abap_data = -value upcase = upcase ).
APPEND rec_xml_string TO xml_fragments.
ENDLOOP.
IF exceptab IS NOT INITIAL.
rec_xml_string = abap2xml( name = 'EXCEPTION' abap_data = exceptab upcase = upcase ).
APPEND rec_xml_string TO xml_fragments.
ENDIF.
CONCATENATE '' l_funcname '>' INTO rec_xml_string.
APPEND rec_xml_string TO xml_fragments.
CONCATENATE LINES OF xml_fragments INTO o_string.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>SERIALIZE_YAML
* +-------------------------------------------------------------------------------------------------+
* | [--->] PARAMTAB TYPE ABAP_FUNC_PARMBIND_TAB
* | [--->] PARAMS TYPE ANY
* | [--->] EXCEPTAB TYPE ABAP_FUNC_EXCPBIND_TAB
* | [--->] SHOW_IMPP TYPE ABAP_BOOL
* | [--->] JSONP TYPE STRING
* | [--->] LOWERCASE TYPE ABAP_BOOL (default =ABAP_FALSE)
* | [<---] YAML_STRING TYPE STRING
* +--------------------------------------------------------------------------------------
METHOD serialize_yaml.
* Now, go and represent function data in YAML (http://yaml.org)
TYPE-POOLS: abap.
** Remember function parameter types
**constants:
** abap_func_exporting type abap_func_parmbind-kind value 10,
** abap_func_importing type abap_func_parmbind-kind value 20,
** abap_func_tables type abap_func_parmbind-kind value 30,
** abap_func_changing type abap_func_parmbind-kind value 40.
DATA yaml_fragments TYPE TABLE OF string.
DATA rec_yaml_string TYPE string.
DATA rec_yaml_table TYPE TABLE OF string.
DATA paramname TYPE string.
FIELD-SYMBOLS TYPE abap_func_parmbind.
FIELD-SYMBOLS TYPE abap_func_excpbind.
DATA upcase TYPE xfeld VALUE 'X'.
DATA yaml_head TYPE string VALUE '--- #YAML:1.0'.
CONCATENATE yaml_head xnl INTO rec_yaml_string.
APPEND rec_yaml_string TO yaml_fragments.
CLEAR rec_yaml_string.
LOOP AT paramtab ASSIGNING .
IF show_impp NE 'X'
AND -kind EQ abap_func_exporting. "" va al revés, cuidado!!!
CONTINUE.
ENDIF.
paramname = -name.
IF lowercase EQ abap_true.
TRANSLATE paramname TO LOWER CASE.
upcase = space.
ENDIF.
rec_yaml_string = abap2yaml( abap_data = -value name = paramname upcase = upcase ).
APPEND rec_yaml_string TO yaml_fragments.
CLEAR rec_yaml_string.
ENDLOOP.
IF exceptab IS NOT INITIAL.
rec_yaml_string = abap2yaml( abap_data = exceptab name = 'EXCEPTION' upcase = 'X' ).
APPEND rec_yaml_string TO yaml_fragments.
CLEAR rec_yaml_string.
ENDIF.
* append xnl to yaml_fragments.
CONCATENATE LINES OF yaml_fragments INTO yaml_string.
* if jsonp is not initial.
* concatenate jsonp '(' yaml_string ');' into yaml_string.
* endif.
ENDMETHOD.
ENDCLASS.
CLASS zcl_log_handler DEFINITION
PUBLIC
FINAL
CREATE PUBLIC .
PUBLIC SECTION.
TYPE-POOLS abap .
METHODS constructor
IMPORTING
!function_name TYPE rs38l_fnam .
METHODS add_paramater
IMPORTING
!name TYPE abap_parmname
!value TYPE any
RAISING
cx_ai_system_fault .
METHODS save_log
IMPORTING
!is_input TYPE zif_msg .
PROTECTED SECTION.
PRIVATE SECTION.
DATA paramtab TYPE abap_func_parmbind_tab .
DATA exceptab TYPE abap_func_excpbind_tab .
DATA:
t_params_p TYPE TABLE OF rfc_fint_p .
ENDCLASS.
CLASS zcl_log_handler IMPLEMENTATION.
* ---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_LOG_HANDLER->ADD_PARAMATER
* +-------------------------------------------------------------------------------------------------+
* | [--->] NAME TYPE ABAP_PARMNAME
* | [--->] VALUE TYPE ANY
* | [!CX!] CX_AI_SYSTEM_FAULT
* +--------------------------------------------------------------------------------------
METHOD add_paramater.
FIELD-SYMBOLS TYPE abap_func_parmbind.
READ TABLE paramtab ASSIGNING WITH KEY name = name.
IF sy-subrc = 0.
GET REFERENCE OF value INTO -value.
ELSE.
RAISE EXCEPTION TYPE cx_ai_system_fault
EXPORTING
code = 'E'
errortext = '输入参数不存在'.
ENDIF.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_LOG_HANDLER->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] FUNCTION_NAME TYPE RS38L_FNAM
* +--------------------------------------------------------------------------------------
METHOD constructor.
REFRESH:paramtab,exceptab,t_params_p.
CALL METHOD zcl_json_handler=>build_params
EXPORTING
function_name = function_name
IMPORTING
paramtab = paramtab
exceptab = exceptab
params = t_params_p
EXCEPTIONS
invalid_function = 1
unsupported_param_type = 2
OTHERS = 3.
IF sy-subrc = 1.
RAISE EXCEPTION TYPE cx_ai_system_fault
EXPORTING
code = 'E'
errortext = '函数名错误'.
ELSEIF sy-subrc <> 0.
RAISE EXCEPTION TYPE cx_ai_system_fault
EXPORTING
code = 'E'
errortext = '函数名错误'.
ENDIF.
ENDMETHOD.
* ---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_LOG_HANDLER->SAVE_LOG
* +-------------------------------------------------------------------------------------------------+
* | [--->] IS_INPUT TYPE ZIF_MSG
* +--------------------------------------------------------------------------------------
METHOD save_log.
DATA:ls_zif_msg TYPE zif_msg.
ls_zif_msg = is_input.
CALL METHOD zcl_json_handler=>serialize_json
EXPORTING
paramtab = paramtab
show_impp = 'X'
IMPORTING
o_string = ls_zif_msg-paylod.
MODIFY zif_msg FROM ls_zif_msg.
COMMIT WORK .
ENDMETHOD.
ENDCLASS.
接口日志展示ALV
report : ZIF_DISPLAY
*& Responsibility
*&---------------------------------------------------------------------*
* Program Name:ZIF_DISPLAY
* Date written:
* Author's name:
* Last update:
* Program title:接口日志查询
* Project Name:
* Version:
*&---------------------------------------------------------------------*
* Description: (Incl. Related Function Area and System)
*&---------------------------------------------------------------------*
*
*&---------------------------------------------------------------------*
* Change History
*&---------------------------------------------------------------------*
* Date | Programmer | Corr. # | Description
* | | |
* | | |
*&---------------------------------------------------------------------*
REPORT zif_display.
DATA: gt_itab TYPE STANDARD TABLE OF zif_msg.
*---------------------------------------------------------------------*
* 选择屏幕
*---------------------------------------------------------------------*
TABLES:usr02.
SELECTION-SCREEN:BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
SELECT-OPTIONS:
s_erdat FOR sy-datum,
s_ernam FOR usr02-bname.
SELECTION-SCREEN END OF BLOCK b1.
*&---------------------------------------------------------------------*
*& START-OF-SELECTION
*&---------------------------------------------------------------------*
START-OF-SELECTION.
PERFORM get_data.
PERFORM display.
FORM get_data .
SELECT *
FROM zif_msg
INTO TABLE gt_itab
WHERE erdat IN s_erdat
AND ernam IN s_ernam.
SORT gt_itab BY erdat DESCENDING uzeit DESCENDING.
ENDFORM. "GET_DATA
*&---------------------------------------------------------------------*
*& Form display
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& --> p1 text
*& <-- p2 text
*&---------------------------------------------------------------------*
FORM display .
DATA:ls_layout TYPE lvc_s_layo.
ls_layout-zebra = 'X'.
ls_layout-cwidth_opt = 'X'.
ls_layout-sel_mode = 'B'.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
EXPORTING
i_callback_program = sy-repid
i_callback_user_command = 'FRM_USER_COMMAND'
is_layout_lvc = ls_layout
i_structure_name = 'ZIF_MSG'
* it_fieldcat_lvc = gt_fieldcat
i_save = 'A'
TABLES
t_outtab = gt_itab
EXCEPTIONS
program_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
ENDFORM.
FORM frm_user_command USING iv_ucomm TYPE sy-ucomm
is_selfield TYPE slis_selfield.
DATA: l_grid TYPE REF TO cl_gui_alv_grid.
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = l_grid.
CALL METHOD l_grid->check_changed_data.
CASE iv_ucomm.
WHEN '&IC1'.
READ TABLE gt_itab INDEX is_selfield-tabindex INTO DATA(ls_itab). "获取单击行
IF sy-subrc IS INITIAL.
PERFORM display_json USING ls_itab.
ENDIF.
* WHEN '&RESEND'.重新发送
* DATA:lt_para_tab TYPE abap_func_parmbind_tab,
* ls_para_line LIKE LINE OF lt_para_tab,
* lt_exceptab TYPE abap_func_excpbind_tab,
* lt_params_p TYPE TABLE OF rfc_fint_p,
* params_p TYPE rfc_fint_p,
* oexcp TYPE REF TO cx_root,
* lv_etext TYPE string.
* FIELD-SYMBOLS TYPE abap_func_parmbind.
* CALL METHOD zcl_json_handler=>build_params
* EXPORTING
* function_name = ls_itab-proname
* IMPORTING
* paramtab = lt_para_tab
* exceptab = lt_exceptab
* params = lt_params_p
* EXCEPTIONS
* invalid_function = 1
* unsupported_param_type = 2
* OTHERS = 3.
* IF sy-subrc <> 0.
* CONCATENATE '函数名错误. ' sy-msgid sy-msgty sy-msgno ': '
* sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
* INTO lv_etext SEPARATED BY '-'.
* MESSAGE lv_etext TYPE 'E'.
* ENDIF.
* TRY.
* CALL METHOD zcl_json_handler=>json_deserialize
* EXPORTING
* json = ls_itab-paylod
* CHANGING
* paramtab = lt_para_tab.
* TRY.
* CALL FUNCTION ls_itab-proname
* PARAMETER-TABLE lt_para_tab
* EXCEPTION-TABLE lt_exceptab.
* CATCH cx_root INTO oexcp.
* lv_etext = oexcp->if_message~get_longtext( preserve_newlines = abap_true ).
* MESSAGE lv_etext TYPE 'E'.
*
* ENDTRY.
* CATCH cx_root INTO oexcp.
* lv_etext = oexcp->if_message~get_text( ).
* MESSAGE lv_etext TYPE 'E'.
* ENDTRY.
ENDCASE.
**刷新
CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
IMPORTING
e_grid = l_grid.
CALL METHOD l_grid->check_changed_data.
CALL METHOD l_grid->refresh_table_display.
is_selfield-refresh = 'X' .
ENDFORM. "frm_user_command
FORM display_json USING is_itab TYPE zif_msg.
DATA:lv_json TYPE string.
DATA(out) = cl_demo_output=>new( ).
DATA :reader TYPE REF TO if_sxml_reader,
writer TYPE REF TO if_sxml_writer,
writer_str TYPE REF TO cl_sxml_string_writer.
DATA json TYPE xstring.
lv_json = is_itab-paylod.
out->begin_section( |函数:{ is_itab-proname }| ).
CHECK lv_json <> ''.
IF lv_json+0(1) = '<'.
out->write_xml( lv_json ).
ELSE.
out->write_json( lv_json ).
ENDIF.
IF sy-subrc <> 0.
MESSAGE '要显示的报文不存在!' TYPE 'S'.
ELSE.
out->display( ).
ENDIF.
ENDFORM.
FUNCTION zdemo_02.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(IV_INPUT) TYPE CHAR10
*" REFERENCE(IV_INPUT2) TYPE CHAR10
*" EXPORTING
*" REFERENCE(EV_MSG) TYPE STRING
*"----------------------------------------------------------------------
*初始化获取函数相关自身信息
DATA: lt_callstack TYPE abap_callstack.
CALL FUNCTION 'SYSTEM_CALLSTACK'
IMPORTING
callstack = lt_callstack.
DATA(lv_func_name) = VALUE #( lt_callstack[ 1 ]-blockname OPTIONAL ).
SELECT funcname, paramtype, pposition, parameter, structure
FROM fupararef
WHERE funcname = @lv_func_name
INTO TABLE @DATA(lt_parameters_tab).
SORT lt_parameters_tab BY paramtype pposition.
*初始化获取函数相关自身信息
TRY.
DATA(lv_uuid) = cl_system_uuid=>create_uuid_c32_static( ).
CATCH cx_uuid_error.
ENDTRY.
ev_msg = 'S'.
*save log
DATA:ls_zif_msg TYPE zif_msg.
DATA:lr_log TYPE REF TO zcl_log_handler.
DATA:lo_sys_exception2 TYPE REF TO cx_ai_system_fault.
.
ls_zif_msg-guid = lv_uuid.
ls_zif_msg-proname = 'ZDEMO_02'.
ls_zif_msg-erdat = sy-datum.
ls_zif_msg-ernam = sy-uname.
ls_zif_msg-uzeit = sy-uzeit.
ls_zif_msg-type = ''.
ls_zif_msg-msg = ''.
* ls_zif_msg-paylod = lv_uuid.
ls_zif_msg-cust_field1 = iv_input.
* ls_zif_msg-cust_field2 = lv_uuid.
* ls_zif_msg-cust_field3 = lv_uuid.
FIELD-SYMBOLS: TYPE any.
TRY.
lr_log = NEW #( CONV #( lv_func_name ) ).
*优化写法
LOOP AT lt_parameters_tab ASSIGNING FIELD-SYMBOL().
ASSIGN (-parameter) TO .
lr_log->add_paramater( name = -parameter value = ).
ENDLOOP.
*原始写法
* lr_log->add_paramater( name = 'IV_INPUT' value = iv_input ).
* lr_log->add_paramater( name = 'EV_MSG' value = ev_msg ).
**原始写法
lr_log->save_log( is_input = ls_zif_msg ).
CATCH cx_ai_system_fault INTO lo_sys_exception2. "
ENDTRY.
ENDFUNCTION.