Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Parse JSON without array name into internal table

ashok_mohan
Participant
0 Likes
1,808

I my report program there is a json string.

[{"duration":258,"length":2051,"status":6},{"duration":333,"length":1623,"status":6},{"duration":523,"length":3367,"status":6},{"duration":540,"length":2921,"status":6},{"duration":380,"length":1302,"status":6},{"duration":1008,"length":4570,"status":6},{"duration":271,"length":1942,"status":6},{"duration":629,"length":3981,"status":6},{"duration":925,"length":4280,"status":6},{"duration":646,"length":3895,"status":6},{"duration":923,"length":4839,"status":6},{"duration":611,"length":2896,"status":6},{"duration":692,"length":3143,"status":6},{"duration":747,"length":3307,"status":6},{"duration":380,"length":2414,"status":6},{"duration":1125,"length":4977,"status":6},{"duration":484,"length":5832,"status":6},{"duration":384,"length":1229,"status":6},{"duration":459,"length":3908,"status":6},{"duration":1216,"length":4664,"status":6},{"duration":299,"length":2244,"status":6},{"duration":751,"length":3442,"status":6},{"duration":1487,"length":6676,"status":6},{"duration":1022,"length":5333,"status":6},{"duration":1620,"length":6792,"status":6},{"duration":1241,"length":6961,"status":6},{"duration":741,"length":4309,"status":6},{"duration":1540,"length":6069,"status":6},{"duration":1578,"length":6580,"status":6},{"duration":890,"length":5754,"status":6},{"duration":488,"length":2902,"status":6},{"duration":288,"length":2785,"status":6},{"duration":562,"length":2016,"status":6},{"duration":756,"length":3454,"status":6},{"duration":478,"length":3712,"status":6},{"duration":1291,"length":4702,"status":6},{"duration":734,"length":5289,"status":6},{"duration":719,"length":4823,"status":6},{"duration":1481,"length":7950,"status":6},{"duration":435,"length":3299,"status":6},{"duration":207,"length":1704,"status":6},{"duration":1197,"length":5029,"status":6},{"duration":561,"length":4100,"status":6},{"duration":609,"length":6206,"status":6},{"duration":858,"length":5799,"status":6},{"duration":1098,"length":8816,"status":6},{"duration":2024,"length":10465,"status":6},{"duration":2649,"length":9847,"status":6},{"duration":1106,"length":8252,"status":6},{"duration":608,"length":3442,"status":6},{"duration":717,"length":4396,"status":6},{"duration":852,"length":6764,"status":6},{"duration":651,"length":5122,"status":6},{"duration":1657,"length":6967,"status":6},{"duration":1059,"length":5298,"status":6},{"duration":1730,"length":8068,"status":6},{"duration":1444,"length":7038,"status":6},{"duration":908,"length":7140,"status":6},{"duration":663,"length":6908,"status":6},{"duration":663,"length":6908,"status":6}]

But here, there is no array name. I have created an internal table with the fields duration, length and name. I want to save the data on to the internal table. When I do CALL TRANSFORMATION it results in  runtime error.  Can anyone tell how to move these values to the internal table?

1 ACCEPTED SOLUTION
Read only

former_member202253
Participant
0 Likes
700

Hello Ashok,

Please find below code,

Let me know if that's work for you...

Pass the table which has all required field.

      CALL METHOD json2abap
        EXPORTING
          json_string = jsondata
          var_name= 'items'
        CHANGING
          abap_data   = lt_order_data.

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,

    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( ).

***************************************************

*  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

    endif.

  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> ).

**

  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 ).

* If the table is empty, try with the lowercase name of the param, to increase the chances of a match.

  if js_property_table is initial.

    translate l_property_path to lower case.

    js_property_table = js_object->get_properties_scope_global( property_path = l_property_path ).

  endif.

  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.

* Translate JS properties to upper case. This is risky, but necessary

* if we want a little interoperability with ABAP structures.

      loop at js_property_table assigning <jsprop>.

        translate <jsprop>-name to upper case.

      endloop.

* Process ABAP structures

      strudesc ?= datadesc.

      loop at strudesc->COMPONENTS into l_comp.

        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 l_comp-name into item_path separated by '.'.

*> Recursive call here

            json2abap( exporting property_path = item_path changing abap_data = <comp> js_object = js_object ).

**        when cl_abap_typedescr=>TYPEKIND_TABLE. " 'h' (may need a different treatment one day)

          when others.

* Process scalars in structures (same as the kind_elem above)

            read table js_property_table with key name = l_comp-name into js_property.

            if sy-subrc eq 0.

              assign_scalar_value <comp> js_property-value.

            endif.

        endcase.

      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>.

        DELETE js_property_table WHERE kind NE 'O'.

        loop at js_property_table into js_property.

          create data newline type (linetype).

          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 ).

          assign newline->* to <comp>.

          insert <comp> into table <itab>.

          free newline.

        endloop.

      endif.

    when others. " kind_class, kind_intf

      " forget it.

  endcase.

endmethod.

Hopefully this will help.

Thanks,

Nikhil

1 REPLY 1
Read only

former_member202253
Participant
0 Likes
701

Hello Ashok,

Please find below code,

Let me know if that's work for you...

Pass the table which has all required field.

      CALL METHOD json2abap
        EXPORTING
          json_string = jsondata
          var_name= 'items'
        CHANGING
          abap_data   = lt_order_data.

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,

    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( ).

***************************************************

*  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

    endif.

  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> ).

**

  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 ).

* If the table is empty, try with the lowercase name of the param, to increase the chances of a match.

  if js_property_table is initial.

    translate l_property_path to lower case.

    js_property_table = js_object->get_properties_scope_global( property_path = l_property_path ).

  endif.

  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.

* Translate JS properties to upper case. This is risky, but necessary

* if we want a little interoperability with ABAP structures.

      loop at js_property_table assigning <jsprop>.

        translate <jsprop>-name to upper case.

      endloop.

* Process ABAP structures

      strudesc ?= datadesc.

      loop at strudesc->COMPONENTS into l_comp.

        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 l_comp-name into item_path separated by '.'.

*> Recursive call here

            json2abap( exporting property_path = item_path changing abap_data = <comp> js_object = js_object ).

**        when cl_abap_typedescr=>TYPEKIND_TABLE. " 'h' (may need a different treatment one day)

          when others.

* Process scalars in structures (same as the kind_elem above)

            read table js_property_table with key name = l_comp-name into js_property.

            if sy-subrc eq 0.

              assign_scalar_value <comp> js_property-value.

            endif.

        endcase.

      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>.

        DELETE js_property_table WHERE kind NE 'O'.

        loop at js_property_table into js_property.

          create data newline type (linetype).

          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 ).

          assign newline->* to <comp>.

          insert <comp> into table <itab>.

          free newline.

        endloop.

      endif.

    when others. " kind_class, kind_intf

      " forget it.

  endcase.

endmethod.

Hopefully this will help.

Thanks,

Nikhil