接口监控平台(简化版)

 SAP ABAP 接口函数日志 简化版

参考博客:

SAP ABAP 接口函数日志 简化版_sap 接口日志-CSDN博客

1、日志存储表

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

2、工具类:zcl_json_handler  json处理
                    zcl_log_handler    保存日志

3接口日志展示ALV: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 <parm> 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.

4、函数DEMO:

FUNCTION zdemo_02.
*"----------------------------------------------------------------------
*"*"本地接口:
*"  IMPORTING
*"     VALUE(IV_INPUT) TYPE  CHAR10
*"     VALUE(IV_INPUT2) TYPE  CHAR10 OPTIONAL
*"     REFERENCE(IT_INPUT) TYPE  ZSSINPUT_T
*"  EXPORTING
*"     VALUE(EV_MSG) TYPE  STRING
*"  TABLES
*"      IT_TAB STRUCTURE  ZSSDI300A OPTIONAL
*"----------------------------------------------------------------------
*初始化获取函数相关自身信息
  DATA: lt_callstack TYPE abap_callstack.
  DATA: lv_tabname   TYPE string.

  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: </afl/parameter>   TYPE any.
  TRY.
      lr_log = NEW #( CONV #( lv_func_name ) ).
*优化写法
      LOOP AT lt_parameters_tab  ASSIGNING FIELD-SYMBOL(<ls_tab>).
        IF <ls_tab>-paramtype NE 'T'.
          ASSIGN (<ls_tab>-parameter) TO </afl/parameter>.
        ELSE.
          lv_tabname = <ls_tab>-parameter && '[]'.
          ASSIGN (lv_tabname) TO </afl/parameter>.
        ENDIF.
        lr_log->add_paramater( name = <ls_tab>-parameter value = </afl/parameter> ).
      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.

zcl_json_handler源码:

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.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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:
      <abap_data> TYPE any,
      <itab>      TYPE ANY TABLE,
      <stru>      TYPE ANY TABLE,
      <comp>      TYPE any,
      <abapcomp>  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 <abap_data>.
      IF sy-subrc NE 0.
        APPEND '{}' TO json_fragments.
        CONCATENATE LINES OF json_fragments INTO json_string.
        EXIT.
      ENDIF.
    ELSE.
      ASSIGN abap_data TO <abap_data>.
    ENDIF.

* Get ABAP data type again and start
    DESCRIBE FIELD <abap_data> 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 <abap_data> TO <itab>.
      l_lines = lines( <itab> ).
      LOOP AT <itab> ASSIGNING <comp>.
        ADD 1 TO l_index.
*> Recursive call for each table row:
        rec_json_string = abap2json( abap_data = <comp> 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( <abap_data> ).
        LOOP AT l_strudescr->components ASSIGNING <abapcomp>.
          l_index = sy-tabix .
          ASSIGN COMPONENT <abapcomp>-name OF STRUCTURE <abap_data> TO <comp>.
          l_name = <abapcomp>-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 <comp> 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 = <comp> 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 <comp> 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 <abap_data> 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.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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:
      <abap_data> TYPE any,
      <itab>      TYPE ANY TABLE,
      <stru>      TYPE ANY TABLE,
      <comp>      TYPE any,
      <abapcomp>  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 <abap_data>.
      IF sy-subrc NE 0.
        APPEND '{}' TO perl_fragments.
        CONCATENATE LINES OF perl_fragments INTO perl_string.
        EXIT.
      ENDIF.
    ELSE.
      ASSIGN abap_data TO <abap_data>.
    ENDIF.
* Get ABAP data type again and start
    DESCRIBE FIELD <abap_data> TYPE l_type COMPONENTS l_comps.
***************************************************
*  Tables
***************************************************
    IF l_type EQ cl_abap_typedescr=>typekind_table.
* '[' Table opening bracket
      APPEND '[' TO perl_fragments.
      ASSIGN <abap_data> TO <itab>.
      l_lines = lines( <itab> ).
      LOOP AT <itab> ASSIGNING <comp>.
        ADD 1 TO l_index.
*> Recursive call here
        rec_perl_string = abap2perl( abap_data = <comp> 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( <abap_data> ) .
        LOOP AT l_typedescr->components ASSIGNING <abapcomp> .
          l_index = sy-tabix .
          ASSIGN COMPONENT <abapcomp>-name OF STRUCTURE <abap_data> TO <comp>.
          l_name = <abapcomp>-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 <comp> 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 = <comp> 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 <comp> 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 <abap_data> 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.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD abap2xml.
*
*/ Look at method serialize_id for a new way of doing XML.
    TYPE-POOLS: abap.
    CONSTANTS:
      xml_head TYPE string VALUE '<?xml version="1.0" encoding="utf-8"?>',
      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:
      <abap_data> TYPE any,
      <itab>      TYPE ANY TABLE,
      <stru>      TYPE ANY TABLE,
      <comp>      TYPE any,
      <abapcomp>  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 <abap_data>.
      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 <abap_data>.
    ENDIF.
* Get ABAP data type again and start
    DESCRIBE FIELD <abap_data> TYPE l_type COMPONENTS l_comps.
***************************************************
*  Tables
***************************************************
    IF l_type EQ cl_abap_typedescr=>typekind_table.
      l_tabledescr ?= cl_abap_typedescr=>describe_by_data( <abap_data> ).
      l_linedescr = l_tabledescr->get_table_line_type( ).
      l_item_str = l_linedescr->get_relative_name( ).
      ASSIGN <abap_data> TO <itab>.
      LOOP AT <itab> ASSIGNING <comp>.
        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 = <comp> 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( <abap_data> ).
        LOOP AT l_typedescr->components ASSIGNING <abapcomp> .
          ASSIGN COMPONENT <abapcomp>-name OF STRUCTURE <abap_data> TO <comp>.
          l_name = <abapcomp>-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 <comp> 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 = <comp> 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 <comp> 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 <abap_data> 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.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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:
      <abap_data> TYPE any,
      <itab>      TYPE ANY TABLE,
      <stru>      TYPE ANY TABLE,
      <comp>      TYPE any.
    DATA l_typedescr TYPE REF TO cl_abap_structdescr .
    FIELD-SYMBOLS <abapcomp> 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 <abap_data>.
      IF sy-subrc NE 0.
        yaml_string = space. " pasamos de poner nada si falla...
        EXIT.
      ENDIF.
    ELSE.
      ASSIGN abap_data TO <abap_data>.
    ENDIF.


* Get ABAP data type again and start
    DESCRIBE FIELD <abap_data> 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 <abap_data> TO <itab>.
      l_lines = lines( <itab> ).
      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 <itab> ASSIGNING <comp>.
          ADD 1 TO l_index.
*> Recursive call here
          rec_yaml_string = abap2yaml( abap_data = <comp> 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( <abap_data> ) .
        CLEAR l_index.
        LOOP AT l_typedescr->components ASSIGNING <abapcomp>.
          ADD 1 TO l_index.
          ASSIGN COMPONENT <abapcomp>-name OF STRUCTURE <abap_data> TO <comp>.
          l_name = <abapcomp>-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 = <comp> 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 = <abap_data>.
        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( <abap_data> ).
            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.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD build_params.

    TYPE-POOLS: abap.

    DATA defval TYPE rs38l_defo.
    DATA dataname TYPE string.
    DATA waref TYPE REF TO data.

    FIELD-SYMBOLS:
      <wa>   TYPE any,
      <temp> 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 <wa>.
      UNASSIGN <temp>.
      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 <wa>.
          len = strlen( defval ).
          remove_enclosing_quotes defval len.
          IF defval = 'SPACE'.
            <wa> = space.
          ELSEIF len > 3 AND defval+0(3) = 'SY-'.
            ASSIGN (defval) TO <temp>.
            <wa> = <temp>.
            UNASSIGN <temp>.
          ELSE.
            IF defval IS NOT INITIAL.
              <wa> = defval.
            ENDIF.
          ENDIF.
          UNASSIGN <wa>.
          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 <temp>.
          <temp> = 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.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>DESERIALIZE_ID
* +-------------------------------------------------------------------------------------------------+
* | [--->] JSON                           TYPE        STRING
* | [<-->] PARAMTAB                       TYPE        ABAP_FUNC_PARMBIND_TAB
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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 <parm> 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 <parm>.
      IF <parm>-kind EQ abap_func_importing. "" va al revés, cuidado!!!
        CONTINUE.
      ENDIF.
      rlin-name  = <parm>-name.
      rlin-value = <parm>-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  <attribute> 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 <attribute>.
          IF <attribute>->qname-name = 'name'.
            <attribute>->set_value(
              to_upper( <attribute>->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.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | 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)
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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:
      <abap_data> TYPE any,
      <itab>      TYPE ANY TABLE,
      <comp>      TYPE any,
      <jsprop>    TYPE LINE OF js_property_tab,
      <abapcomp>  TYPE abap_compdescr.


    DEFINE assign_scalar_value.
      "   &1   <abap_data>
      "   &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 <abap_data>.
    ELSE.
      ASSIGN abap_data TO <abap_data>.
    ENDIF.
    datadesc = cl_abap_typedescr=>describe_by_data( <abap_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 <abap_data> js_property-value.
        ENDIF.
      WHEN cl_abap_typedescr=>kind_struct.
* Process ABAP structures
        strudesc ?= datadesc.
        LOOP AT js_property_table ASSIGNING <jsprop>.
          compname = <jsprop>-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 <abap_data> TO <comp>.
            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 <jsprop>-name INTO item_path SEPARATED BY '.'.
*> Recursive call here
                json2abap( EXPORTING property_path = item_path CHANGING abap_data = <comp> js_object = js_object ).

              WHEN OTHERS.
* Process scalars in structures (same as the kind_elem above)
                assign_scalar_value <comp> <jsprop>-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 <abap_data> TO <itab>.
          LOOP AT js_property_table INTO js_property WHERE name NE 'length'. " the JS object length
            CREATE DATA newline TYPE (linetype).
            ASSIGN newline->* TO <comp>.
            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 <comp> js_property-value.
            ENDCASE.
            INSERT <comp> INTO TABLE <itab>.
            FREE newline.
          ENDLOOP.
        ENDIF.
      WHEN OTHERS. " kind_class, kind_intf
        " forget it.
    ENDCASE.
  ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Static Public Method ZCL_JSON_HANDLER=>JSON_DESERIALIZE
* +-------------------------------------------------------------------------------------------------+
* | [--->] JSON                           TYPE        STRING
* | [<-->] PARAMTAB                       TYPE        ABAP_FUNC_PARMBIND_TAB
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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 <js_prop> TYPE LINE OF js_property_tab.
    FIELD-SYMBOLS <parm>    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 <js_prop>.
      paramname = <js_prop>-name.
      TRANSLATE paramname TO UPPER CASE.
      READ TABLE paramtab WITH KEY name = paramname ASSIGNING <parm>.
      IF sy-subrc EQ 0.
        IF <parm>-kind NE abap_func_importing. "" va al revés, cuidado!!!
          json2abap( EXPORTING var_name = <js_prop>-name  CHANGING abap_data = <parm>-value js_object = js_obj ).
        ENDIF.
      ENDIF.
    ENDLOOP.
  ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_JSON_HANDLER->NOTES
* +-------------------------------------------------------------------------------------------------+
* | [<-()] TEXT                           TYPE        STRING
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD notes.
    DATA location TYPE string.
    CONCATENATE me->my_url me->my_service '/RFC_SYSTEM_INFO' INTO location.
    CONCATENATE
    '<html><head><title>JSON (NEW) handler notes</title></head><body>'
    '<h4>About this service...</h4>'
    'This is the ABAP implementation of a conversion program that'
    ' tranforms ABAP data into a <a href="http://www.json.org">JSON</a> representation.'
    '<p>'
    '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.'
    '<p>In this system this service has '
    'been assigned to ICF service <a href="' me->my_url me->my_service '">' me->my_service '</a>.'
    '<p>'
    '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.'
    '<p>Try the following link to do the default call in JSON format:<pre><a href="' location '?format=json">'
    location
    '?format=json</a></pre>'
    '<p>A simple syntax allows to get the output in different formats.<p>'
    'The following gets the output in <a href="http://yaml.org">YAML</a> format:'
    '<pre><a href="' location '?format=yaml">'
    location
    '?format=yaml</a></pre>'
    ''
    '<p>And this will get the output in a basic XML representation: <pre><a href="' location '?format=xml">'
    location
    '?format=xml</a></pre>'
    '<p>And, just for fun, getting it into Perl format could be handy: <pre><a href="' location '?format=perl">'
    location
    '?format=perl</a></pre>'
    '<p>Finnally, you can add a callback to get the JSON response enclosed in a javascript function call,'
    ' in order to allow a <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a> style response: '
    '<pre><a href="'
    location '?format=json&callback=callMe">'
    location '?format=json&callback=callMe</a></pre>'
    '<hr><h4>WARNING</h4>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.'
    '<p>Use it at your own risk!'
    '<p>For more information: <a href="https://cw.sdn.sap.com/cw/groups/json-adapter-for-abap-function-modules">'
    'https://cw.sdn.sap.com/cw/groups/json-adapter-for-abap-function-modules</a>'
    '<p>'
    'If you have any questions, please contact me at <a href="mailto:cesar.martin@sap.com">'
    'cesar.martin@sap.com</a>'
    '<p>'
    '<hr></body></html>'
    INTO text RESPECTING BLANKS.
  ENDMETHOD.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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 <parm> TYPE abap_func_parmbind.
*  field-symbols <excep> type abap_func_excpbind.
    LOOP AT paramtab ASSIGNING <parm>.
      IF show_impp NE 'X'
            AND <parm>-kind EQ abap_func_exporting. "" va al revés, cuidado!!!
        CONTINUE.
      ENDIF.
      slin-name  = <parm>-name.
      slin-value = <parm>-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.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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 <parm> TYPE abap_func_parmbind.
    FIELD-SYMBOLS <excep> 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 <parm>.
      IF show_impp NE 'X'
            AND <parm>-kind EQ abap_func_exporting. "" va al revés, cuidado!!!
        SUBTRACT 1 FROM l_lines.
        CONTINUE.
      ENDIF.
      ADD 1 TO l_index.
      paramname = <parm>-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 = <parm>-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.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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 <parm> TYPE abap_func_parmbind.
    FIELD-SYMBOLS <excep> 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 <parm>.
      IF show_impp NE 'X'
            AND <parm>-kind EQ abap_func_exporting. "" va al revés, cuidado!!!
        SUBTRACT 1 FROM l_lines.
        CONTINUE.
      ENDIF.
      ADD 1 TO l_index.
      paramname = <parm>-name.
      IF lowercase EQ abap_true.
        TRANSLATE paramname TO LOWER CASE.
        upcase = space.
      ENDIF.
      rec_perl_string = abap2perl( abap_data = <parm>-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.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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 <parm> TYPE abap_func_parmbind.
    FIELD-SYMBOLS <excep> TYPE abap_func_excpbind.
    DATA upcase TYPE xfeld VALUE 'X'.

    CONSTANTS:
       xml_head TYPE string VALUE '<?xml version="1.0" encoding="utf-8"?>'.

    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 <parm>.
      IF show_impp NE 'X'
            AND <parm>-kind EQ abap_func_exporting. "" va al revés, cuidado!!!
        CONTINUE.
      ENDIF.
      paramname = <parm>-name.
      IF lowercase EQ abap_true.
        TRANSLATE paramname TO LOWER CASE.
      ENDIF.
      rec_xml_string = abap2xml( name = paramname abap_data = <parm>-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.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | 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
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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 <parm> TYPE abap_func_parmbind.
    FIELD-SYMBOLS <excep> 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 <parm>.
      IF show_impp NE 'X'
            AND <parm>-kind EQ abap_func_exporting. "" va al revés, cuidado!!!
        CONTINUE.
      ENDIF.
      paramname = <parm>-name.
      IF lowercase EQ abap_true.
        TRANSLATE paramname TO LOWER CASE.
        upcase = space.
      ENDIF.
      rec_yaml_string = abap2yaml( abap_data = <parm>-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.

zcl_log_handler源码:

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.
 
 
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_LOG_HANDLER->ADD_PARAMATER
* +-------------------------------------------------------------------------------------------------+
* | [--->] NAME                           TYPE        ABAP_PARMNAME
* | [--->] VALUE                          TYPE        ANY
* | [!CX!] CX_AI_SYSTEM_FAULT
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD add_paramater.
    FIELD-SYMBOLS <parm> TYPE abap_func_parmbind.
    READ TABLE paramtab ASSIGNING <parm> WITH KEY name = name.
    IF sy-subrc = 0.
      GET REFERENCE OF value INTO <parm>-value.
    ELSE.
 
      RAISE EXCEPTION TYPE cx_ai_system_fault
        EXPORTING
          code      = 'E'
          errortext = '输入参数不存在'.
 
    ENDIF.
  ENDMETHOD.
 
 
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_LOG_HANDLER->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] FUNCTION_NAME                  TYPE        RS38L_FNAM
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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.
 
 
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_LOG_HANDLER->SAVE_LOG
* +-------------------------------------------------------------------------------------------------+
* | [--->] IS_INPUT                       TYPE        ZIF_MSG
* +--------------------------------------------------------------------------------------</SIGNATURE>
  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.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值