* Quelle: https://github.com/i042416/KnowlegeRepository/blob/master/ABAP/SmallApp/011_ZCL_JERRY_TOOL.abap
CLASS lcl_json_parser DEFINITION.
PUBLIC SECTION.
TYPES: BEGIN OF ty_node,
type TYPE string,
prefix TYPE string,
name TYPE string,
nsuri TYPE string,
value TYPE string,
value_raw TYPE xstring,
END OF ty_node.
TYPES: ty_it_node TYPE STANDARD TABLE OF ty_node WITH DEFAULT KEY.
CONSTANTS: co_open_element TYPE string VALUE 'OPEN'.
CONSTANTS: co_close_element TYPE string VALUE 'CLOSE'.
CONSTANTS: co_attribute TYPE string VALUE 'ATTRIBUTE'.
CONSTANTS: co_value TYPE string VALUE 'VALUE'.
CLASS-METHODS: convert_json_to_node_table
IMPORTING
iv_json TYPE string
RETURNING VALUE(rv_it_nodes) TYPE ty_it_node
RAISING
cx_sxml_parse_error.
ENDCLASS.
CLASS lcl_json_parser IMPLEMENTATION.
METHOD convert_json_to_node_table.
* JSON nach XSTRING (UTF-8) konvertieren
DATA(o_json) = cl_abap_codepage=>convert_to( iv_json ).
* XSTRING einlesen und nach XML parsen
DATA(o_reader) = cl_sxml_string_reader=>create( o_json ).
TRY.
* erste Node holen
DATA(o_node) = o_reader->read_next_node( ).
* solange es Nodes gibt
WHILE o_node IS BOUND.
* Node-Typen prüfen
CASE o_node->type.
* Öffnen-Node
WHEN if_sxml_node=>co_nt_element_open.
DATA(op) = CAST if_sxml_open_element( o_node ).
APPEND VALUE #( type = co_open_element
prefix = op->prefix
name = op->qname-name
nsuri = op->qname-namespace ) TO rv_it_nodes.
* Attribute
LOOP AT op->get_attributes( ) ASSIGNING FIELD-SYMBOL(<a>).
APPEND VALUE #( type = co_attribute
prefix = <a>->prefix
name = <a>->qname-name
nsuri = <a>->qname-namespace
value = COND #( WHEN <a>->value_type = if_sxml_value=>co_vt_text THEN <a>->get_value( ) )
value_raw = COND #( WHEN <a>->value_type = if_sxml_value=>co_vt_raw THEN <a>->get_value_raw( ) ) ) TO rv_it_nodes.
ENDLOOP.
* Schließen-Node
WHEN if_sxml_node=>co_nt_element_close.
DATA(cl) = CAST if_sxml_close_element( o_node ).
APPEND VALUE #( type = co_close_element
prefix = cl->prefix
name = cl->qname-name
nsuri = cl->qname-namespace ) TO rv_it_nodes.
* Wert-Node
WHEN if_sxml_node=>co_nt_value.
DATA(val) = CAST if_sxml_value_node( o_node ).
APPEND VALUE #( type = co_value
value = COND #( WHEN val->value_type = if_sxml_value=>co_vt_text THEN val->get_value( ) )
value_raw = COND #( WHEN val->value_type = if_sxml_value=>co_vt_raw THEN val->get_value_raw( ) ) ) TO rv_it_nodes.
* Andere Nodetypen
WHEN OTHERS.
ENDCASE.
* nächste Node
o_node = o_reader->read_next_node( ).
ENDWHILE.
CATCH cx_root INTO DATA(e_txt).
RAISE EXCEPTION TYPE cx_sxml_parse_error
EXPORTING
error_text = e_txt->get_text( ).
ENDTRY.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
TRY.
* JSON-Beispiele
* DATA(lv_json) = CONV string( '{"success":"true","msg":"Ok.","matnr":"0000001234"}' ).
DATA(lv_json) = CONV string( '{"VALUES":[{"NAME":"Horst","TITLE":"Herr","AGE":30},{"NAME":"Jutta","TITLE":"Frau","AGE":35},{"NAME":"Ingo","TITLE":"Herr","AGE":31}]}' ).
* JSON -> Nodetable
DATA(it_node_values) = lcl_json_parser=>convert_json_to_node_table( lv_json ).
* Datenausgabe
cl_demo_output=>write_data( lv_json ).
cl_demo_output=>write_data( it_node_values ).
cl_demo_output=>display( ).
CATCH cx_root INTO DATA(e_txt).
WRITE: / e_txt->get_text( ).
ENDTRY.