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

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)

ABAP Quick - Processing in a new task

Category - ABAP

This tip is about asynchronous processing in a new process and what to look out for.

01/07/2022

ABAP Quick - External currency to internal

Category - ABAP

A little tip to convert data from an Excel or CSV file into the correct internal currency format. A simple conversion can quickly lead to errors.

12/03/2021

ABAP Quick - Creation of test data

Category - ABAP

What challenges do you have when setting up test tables and test data and how can machine processing help you?

06/25/2021

ABAP Unit Quick Guide

Category - ABAP

Our current e-book is now available on Amazon, we would like to briefly show you what you can expect in the book and what it will bring you in the end.

05/28/2021

ABAP Quick - RFC Buffer

Category - ABAP

Here is a little tip from us about what can go wrong with the buffer when reading via RFC and what you should definitely pay attention to.

04/23/2021