READ TABLE WITH TABLE KEY does not find record

Viewed 751

I'm trying to use the class /ui5/cl_json_parser for parsing a JSON string.

The following code snippet reproduces the problem:

REPORT ztest_json_parse.

DATA: input TYPE string,
      output TYPE string,
      json_parser TYPE REF TO /ui5/cl_json_parser.


input = '{"address":[{"street":"Road","number":"545"},{"street":"Avenue","number":"15"}]}'.
CREATE OBJECT json_parser.

json_parser->parse( input ).
json_parser->print( ).

output = json_parser->value( path = '/address/1/street' ).

WRITE output.

The print method shows the correct parsed JSON string, but the output variable is always empty.

I have traced the code down to the method VALUE of the class /UI5/CL_JSON_PARSER, at line 15, which contains:

read table m_entries into l_entry with table key parent = l_parent name = l_name.

In the debugger, I can see that l_parent = '/address/1' and l_name = 'street', and that the internal table m_entries contains a record with parent = '/address/1' and name = 'street'. Nevertheless the READ statement always returns sy-subrc = 4 and does not find anything.

Can anyone help?

2 Answers

First: Do not use /ui5/cl_json_parser class, it is intended for internal use ONLY and has no reliable documentation

enter image description here

Secondly, here is the sample how you can fetch street value from the first element of your JSON:

DATA(o_json) = cl_abap_codepage=>convert_to( '{"address":[{"street":"Road","number":"545"},{"street":"Avenue","number":"15"}]' ).
DATA(o_reader) = cl_sxml_string_reader=>create( o_json ).

TRY.
    DATA(o_node) = o_reader->read_next_node( ).
    WHILE o_node IS BOUND.
      DATA(op) = CAST if_sxml_open_element( o_node ).
      LOOP AT op->get_attributes( ) ASSIGNING FIELD-SYMBOL(<a>).
        DATA(attr) = <a>->get_value( ).
      ENDLOOP.
       IF attr <> 'street'.
         o_node = o_reader->read_next_node( ).
       ELSE.
         DATA(val) = CAST if_sxml_value_node( o_reader->read_next_node( ) ).
         WRITE: '/address/1/street =>', val->get_value( ).
         EXIT.
       ENDIF.
    ENDWHILE.
  CATCH cx_root INTO DATA(e_txt).
ENDTRY.

As far as I know, there is no class in ABAP that allows fetching single JSON attributes like XPath.

Certainly agree with Suncatcher on avoid UI5 Json parser. If you dont control/know the structure of the source data, Suncatchers answer is good.

However, if you know the basic structure of the source JSON and you must, if you plan to access the first address row, fieldname street . AND you can have the source provided using uppercase variable names then you can use the so called identity transformation.

types: begin of ty_addr,
     street type string,
     number type string,
     end of ty_addr.
types ty_addr_t type STANDARD TABLE OF ty_addr.

 DATA: input TYPE string,
       ls_addr TYPE ty_addr,
       lt_addr type ty_addr_t.

input = '{"ADDRESS":[{"STREET":"Road","NUMBER":"545"},{"STREET":"Avenue","NUMBER":"15"}]}'.

CALL TRANSFORMATION id SOURCE XML input
                           RESULT address = lt_addr.

 read table lt_addr index 1 into ls_addr.
 WRITE ls_addr-street.
Related