This is a test message to test the length of the message box.
Login
ABAP Quick Convert JSON to internal
Created by Software-Heroes

ABAP Quick - Convert JSON to internal

8386

In this little tip, we'll go into how you can convert a JSON stream to an internal format and then use it properly.



If you think about the interface landscape today, you won't be able to get around OData for better or for worse. Likewise if you want to connect a cloud system like Ariba or Successfactors. What all these systems have in common is that they communicate with REST interfaces. But how do you process the response data when you address such a service with an HTTP request from ABAP? We'll go into that in a little more detail today.

 

Preperation

In the first step, we build a suitable JSON that consists of different data types and uses a table internally so that we can also work with a deep/nested structure. Our example structure could look like this:

 

Now that we have a JSON string to be converted, we also want to convert this within a program run and fill an internal structure. We can also set up this structure in ABAP, for which we need different types.

TYPES:
  BEGIN OF ts_subdata,
    key   TYPE string,
    value TYPE string,
  END OF ts_subdata,
  tt_subdata TYPE STANDARD TABLE OF ts_subdata WITH EMPTY KEY,

  BEGIN OF ts_data,
    text   TYPE string,
    number TYPE i,
    bool   TYPE abap_bool,
    table  TYPE tt_subdata,
  END OF ts_data.

 

Structure assignment

This is the easiest form of conversion, but you always have to know what your data looks like in order to access the content. Building nested structures can also take some time. In the next step we can already parse the string with the method.

DATA:
  ls_data TYPE ts_data.

/ui2/cl_json=>deserialize(
  EXPORTING
    json             = id_json
  CHANGING
    data             = ls_data
).

 

We create a structure of our target type and then use the DESERIALIZE method of the class /UI2/CL_JSON to carry out the conversion. The data is neatly mapped into the fields and the table, elements that are missing in our structure are simply skipped and we can concentrate on the important content.

 

The ADD_TEXT field is not mapped, but does not lead to an error either. The BOOL field was properly converted to ABAP_TRUE. This provides us with a simple type of conversion.

 

Generic way

We can also perform a conversion completely generically; the method can also generate a reference to the data if we do not pass a structured type. The result of such a conversion looks like this in the Eclipse debugger.

 

We cannot simply access such completely generic data at runtime because the system does not know how the data type is structured. However, we can access and map the data via generic processing. In our example we want to access our unneeded element and map the table within the structure.

DATA:
  lr_data     TYPE REF TO data,
  ld_add_text TYPE string,
  lt_subdata  TYPE tt_subdata.
FIELD-SYMBOLS:
  <lt_table> TYPE STANDARD TABLE.

/ui2/cl_json=>deserialize(
  EXPORTING
    json             = id_json
  CHANGING
    data             = lr_data
).

ASSIGN lr_data->* TO FIELD-SYMBOL(<ls_data>).

" Map the ADD_TEXT field
ASSIGN COMPONENT 'ADD_TEXT' OF STRUCTURE <ls_data> TO FIELD-SYMBOL(<ld_add>).
ASSIGN <ld_add>->* TO FIELD-SYMBOL(<ld_add_value>).
ld_add_text = <ld_add_value>.

" Map internal table 
ASSIGN COMPONENT 'TABLE' OF STRUCTURE <ls_data> TO FIELD-SYMBOL(<lt_table_ref>).
ASSIGN <lt_table_ref>->* TO <lt_table>.

LOOP AT <lt_table> ASSIGNING FIELD-SYMBOL(<ls_line>).
  ASSIGN <ls_line>->* TO FIELD-SYMBOL(<ls_line_value>).

  ASSIGN COMPONENT 'KEY' OF STRUCTURE <ls_line_value> TO FIELD-SYMBOL(<ld_key>).
  ASSIGN COMPONENT 'VALUE' OF STRUCTURE <ls_line_value> TO FIELD-SYMBOL(<ld_value>).

  ASSIGN <ld_key>->* TO FIELD-SYMBOL(<ld_key_value>).
  ASSIGN <ld_value>->* TO FIELD-SYMBOL(<ld_value_value>).

  INSERT VALUE #(
    key   = <ld_key_value>
    value = <ld_value_value>
  ) INTO TABLE lt_subdata.
ENDLOOP.

 

You will certainly think of a lot of code and many ASSIGNs. Each element is a reference and must be double-bound in order to get to the actual value and the actual data. You will surely agree with us that this path is not particularly easy and that it has many pitfalls. Likewise, the entire error handling in the upper part of the source code is still missing, this would take away the same number of lines again.

 

Example

Here again the complete example class as we use it in the examples.

CLASS zcl_60bs_test_json_convert DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PROTECTED SECTION.
  PRIVATE SECTION.
    TYPES:
      BEGIN OF ts_subdata,
        key   TYPE string,
        value TYPE string,
      END OF ts_subdata,
      tt_subdata TYPE STANDARD TABLE OF ts_subdata WITH EMPTY KEY,

      BEGIN OF ts_data,
        text   TYPE string,
        number TYPE i,
        bool   TYPE abap_bool,
        table  TYPE tt_subdata,
      END OF ts_data.

    METHODS:
      convert_json_with_structured
        IMPORTING
          id_json TYPE string,

      convert_json_with_reference
        IMPORTING
          id_json TYPE string.
ENDCLASS.

CLASS zcl_60bs_test_json_convert IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    DATA(ld_json) = `{"text":"Some text","number":123, "bool":"TRUE", "add_text":"Text number 2", "table":[{"key":"One","value":"1"},{"key":"Two","value":"2"}]}`.

    convert_json_with_structured( ld_json ).
    convert_json_with_reference( ld_json ).
  ENDMETHOD.


  METHOD convert_json_with_structured.
    DATA:
      ls_data TYPE ts_data.

    /ui2/cl_json=>deserialize(
      EXPORTING
        json             = id_json
      CHANGING
        data             = ls_data
    ).
  ENDMETHOD.


  METHOD convert_json_with_reference.
    DATA:
      lr_data     TYPE REF TO data,
      ld_add_text TYPE string,
      lt_subdata  TYPE tt_subdata.
    FIELD-SYMBOLS:
      <lt_table> TYPE STANDARD TABLE.

    /ui2/cl_json=>deserialize(
      EXPORTING
        json             = id_json
      CHANGING
        data             = lr_data
    ).

    ASSIGN lr_data->* TO FIELD-SYMBOL(<ls_data>).

    ASSIGN COMPONENT 'ADD_TEXT' OF STRUCTURE <ls_data> TO FIELD-SYMBOL(<ld_add>).
    ASSIGN <ld_add>->* TO FIELD-SYMBOL(<ld_add_value>).
    ld_add_text = <ld_add_value>.

    ASSIGN COMPONENT 'TABLE' OF STRUCTURE <ls_data> TO FIELD-SYMBOL(<lt_table_ref>).
    ASSIGN <lt_table_ref>->* TO <lt_table>.

    LOOP AT <lt_table> ASSIGNING FIELD-SYMBOL(<ls_line>).
      ASSIGN <ls_line>->* TO FIELD-SYMBOL(<ls_line_value>).

      ASSIGN COMPONENT 'KEY' OF STRUCTURE <ls_line_value> TO FIELD-SYMBOL(<ld_key>).
      ASSIGN COMPONENT 'VALUE' OF STRUCTURE <ls_line_value> TO FIELD-SYMBOL(<ld_value>).

      ASSIGN <ld_key>->* TO FIELD-SYMBOL(<ld_key_value>).
      ASSIGN <ld_value>->* TO FIELD-SYMBOL(<ld_value_value>).

      INSERT VALUE #(
        key   = <ld_key_value>
        value = <ld_value_value>
      ) INTO TABLE lt_subdata.
    ENDLOOP.
  ENDMETHOD.
ENDCLASS.

 

Conclusion

Converting a JSON to ABAP can be very easy, but it can also cause a lot of headache if you try to approach it dynamically. We recommend the variant with the predefined structure, as this is much easier to implement.


Included topics:
QuickConvert JSONJSON to internal
Comments (0)



And further ...

Are you satisfied with the content of the article? We post new content in the ABAP area every Friday and irregularly in all other areas. Take a look at our tools and apps, we provide them free of charge.


ABAP in Practice - String Processing

Category - ABAP

In this practical example we look at the string processing to determine the CDS names in CamelCase and how you can implement this with ABAP.

10/15/2024

ABAP in Practice - Test Driven Development

Category - ABAP

How does TDD actually work in practice and are there simple examples for learning in ABAP? In this exercise we will look at the practical part.

09/24/2024

ABAP in Practice - Merge data sets

Category - ABAP

How do we merge two different data sets in ABAP, especially with regard to Modern ABAP? A practical task for this topic.

09/17/2024

ABAP in Practice - Modern ABAP

Category - ABAP

In this small task we look at existing classic ABAP source code and try to optimize it according to Modern ABAP.

08/27/2024

ABAP Quick - Performance Data Filtering

Category - ABAP

Which statement do you use in ABAP to filter internal tables and is it performant? Read more in this article.

08/13/2024