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

JSON Deserialization in ABAP

maklucksap
Advisor
Advisor
31,492

Dear SAP community,

I hope you can help me with JSON Deserialization in SAP. I receive a JSON string and want to convert it into an internal table. Below you can see an example, which is working, but it doesn't behave like a normal JSON deserialization.

These are the issues:

  • If the fields in the JSON string are not in the exact sequence (just switch "FirstField" and "SecondField" in the JSON input file), then the transformation dumps. Usually JSON deserializations should find the match regardless of the field sequence.
  • How can I declare a real boolean value? In my example the boolean value is only working as a string with encapsuled in quotas (").
  • To test this you have to create the below report and the below transformation.

    This is the Report:

    *&---------------------------------------------------------------------*
    *& Report ZJSON_SEQUENCE
    *&---------------------------------------------------------------------*
    report zjson_sequence.
    
    parameters: p_file type string obligatory.
    
    class gcl_json definition.
      public section.
        class-methods main.
    endclass.
    
    class gcl_json implementation.
      method main.
        types: begin of lty_data,
                 firstfield  type c length 10,
                 secondfield type boole_d,
               end of lty_data.
    
        data: lt_string type table of string,
              lt_data   type table of lty_data,
              lv_string type string.
    
        call function 'GUI_UPLOAD'
          exporting
            filename = p_file
          tables
            data_tab = lt_string
          exceptions
            others   = 1.
        if sy-subrc <> 0.
          message id sy-msgid type sy-msgty number 
                     sy-msgno with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
        endif.
    
        loop at lt_string assigning field-symbol(<lv_string>).
          concatenate lv_string <lv_string> into lv_string.
        endloop.
    
        call transformation zjson_sequence source xml lv_string
                                               result root = lt_data.
    
        loop at lt_data assigning field-symbol(<ls_data>).
          write: 'First field = ', <ls_data>-firstfield, 
                 '; Second field = ', <ls_data>-secondfield.
          skip.
        endloop.
      endmethod.
    endclass.
    
    at selection-screen on value-request for p_file.
      call function 'WS_FILENAME_GET'
        importing
          filename = p_file
        exceptions
          others   = 1.
    
    start-of-selection.
      gcl_json=>main( ).
    

    This is the Transformation:

    <?sap.transform simple?>
    <tt:transform xmlns:tt="http://www.sap.com/transformation-templates">
      <tt:root name="ROOT"/>
      <tt:template>
      <object>
        <array name="SomeData">
          <tt:loop ref=".ROOT">
            <object>
              <str name="FirstField">
    	    <tt:value ref="$ref.firstfield"/>
    	  </str>
              <str name="SecondField">
    	    <tt:value option="format(boolean)" 
    			 ref="$ref.secondfield"/>
     	  </str>
           </object>
          </tt:loop>
        </array>
      </object>
      </tt:template>
    </tt:transform>
    

    This is the JSON example, which works. It needs to be saved as a text file and uploaded by the report:

    {
     "SomeData":
     [
      {
       "FirstField": "ABCDE12345",
       "SecondField": "true"
      }
     ]
    }
    

    This is the JSON example, which doesn't work:

    {
     "SomeData":
     [
      {
       "SecondField": true,
       "FirstField": "ABCDE12345"
      }
     ]
    }
    

    Looking forward for your guidance.

    Kind Regards
    Mark André

    1 ACCEPTED SOLUTION
    Read only

    Florian
    SAP Champion
    SAP Champion
    16,189

    why not use something which is working well.

    For example this one:

    https://wiki.scn.sap.com/wiki/display/Snippets/One+more+ABAP+to+JSON+Serializer+and+Deserializer

    https://blogs.sap.com/2013/02/21/three-different-ways-to-serialize-and-deserialize-complex-abap-data...

    I think the issue with the boolean might be fixed, but not sure, because it's a while ago I used it (first link).

    Dear SAP community,

    I hope you can help me with JSON Deserialization in SAP. I receive a JSON string and want to convert it into an internal table. Below you can see an example, which is working, but it doesn't behave like a normal JSON deserialization.

    These are the issues:

  • If the fields in the JSON string are not in the exact sequence (just switch "FirstField" and "SecondField" in the JSON input file), then the transformation dumps. Usually JSON deserializations should find the match regardless of the field sequence.
  • How can I declare a real boolean value? In my example the boolean value is only working as a string with encapsuled in quotas (").
  • To test this you have to create the below report and the below transformation.

    This is the Report:

    *&---------------------------------------------------------------------*
    *& Report ZJSON_SEQUENCE
    *&---------------------------------------------------------------------*
    report zjson_sequence.
    
    parameters: p_file type string obligatory.
    
    class gcl_json definition.
      public section.
        class-methods main.
    endclass.
    
    class gcl_json implementation.
      method main.
        types: begin of lty_data,
                 firstfield  type c length 10,
                 secondfield type boole_d,
               end of lty_data.
    
        data: lt_string type table of string,
              lt_data   type table of lty_data,
              lv_string type string.
    
        call function 'GUI_UPLOAD'
          exporting
            filename = p_file
          tables
            data_tab = lt_string
          exceptions
            others   = 1.
        if sy-subrc <> 0.
          message id sy-msgid type sy-msgty number 
                     sy-msgno with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
        endif.
    
        loop at lt_string assigning field-symbol(<lv_string>).
          concatenate lv_string <lv_string> into lv_string.
        endloop.
    
        call transformation zjson_sequence source xml lv_string
                                               result root = lt_data.
    
        loop at lt_data assigning field-symbol(<ls_data>).
          write: 'First field = ', <ls_data>-firstfield, 
                 '; Second field = ', <ls_data>-secondfield.
          skip.
        endloop.
      endmethod.
    endclass.
    
    at selection-screen on value-request for p_file.
      call function 'WS_FILENAME_GET'
        importing
          filename = p_file
        exceptions
          others   = 1.
    
    start-of-selection.
      gcl_json=>main( ).
    

    This is the Transformation:

    <?sap.transform simple?>
    <tt:transform xmlns:tt="http://www.sap.com/transformation-templates">
      <tt:root name="ROOT"/>
      <tt:template>
      <object>
        <array name="SomeData">
          <tt:loop ref=".ROOT">
            <object>
              <str name="FirstField">
    	    <tt:value ref="$ref.firstfield"/>
    	  </str>
              <str name="SecondField">
    	    <tt:value option="format(boolean)" 
    			 ref="$ref.secondfield"/>
     	  </str>
           </object>
          </tt:loop>
        </array>
      </object>
      </tt:template>
    </tt:transform>
    

    This is the JSON example, which works. It needs to be saved as a text file and uploaded by the report:

    {
     "SomeData":
     [
      {
       "FirstField": "ABCDE12345",
       "SecondField": "true"
      }
     ]
    }
    

    This is the JSON example, which doesn't work:

    {
     "SomeData":
     [
      {
       "SecondField": true,
       "FirstField": "ABCDE12345"
      }
     ]
    }
    

    Looking forward for your guidance.

    Kind Regards
    Mark André

    9 REPLIES 9
    Read only

    Sandra_Rossi
    Active Contributor
    16,189

    When you use CALL TRANSFORMATION and the input string is JSON, it automatically converts it into XML, and then the transformation is applied. So your question is about how to allow elements in any order in a Simple Transformation -> cf <tt:group>

    Read only

    16,189

    Hi Sandra,

    thank you for the hint. This has solved the field sequence issue. I was also able to sort out the boolean value issue. With this transformation both issues are fixed:

    <?sap.transform simple?>
    <tt:transform xmlns:tt="http://www.sap.com/transformation-templates">
      <tt:root name="ROOT"/>
      <tt:template>
      <object>
        <array name="SomeData">
          <tt:loop ref=".ROOT">
            <object>
            <tt:group>
            <tt:d-cond frq="*">
              <str name="FirstField"><tt:value ref="$ref.firstfield"/></str>
            </tt:d-cond>
            <tt:d-cond frq="*">
              <bool name="SecondField"><tt:value option="format(boolean)" ref="$ref.secondfield"/></bool>
            </tt:d-cond>
            </tt:group>
           </object>
          </tt:loop>
        </array>
      </object>
      </tt:template>
    </tt:transform>

    I have one more problem. I want it to be possible that fields are missing in JSON or that additina fields are possible in JSON, which are just not taken into account, because they are missing in the ABAP structure. But if I try this I always get a short dump.

    In general is this the correct approach to write a transformation and deserialize the JSON directly with CALL TRANSFORMATION into an internal table? Or is the better approach maybe working with a JSON Reader class and handle the parsing in ABAP?

    Kind Regards
    Mark André

    Read only

    16,189

    maklucksap tt:cond is for that, the question is what dump do you get? If your transformation is too complex then deserialize with a class.

    Read only

    Florian
    SAP Champion
    SAP Champion
    16,190

    why not use something which is working well.

    For example this one:

    https://wiki.scn.sap.com/wiki/display/Snippets/One+more+ABAP+to+JSON+Serializer+and+Deserializer

    https://blogs.sap.com/2013/02/21/three-different-ways-to-serialize-and-deserialize-complex-abap-data...

    I think the issue with the boolean might be fixed, but not sure, because it's a while ago I used it (first link).

    Read only

    0 Likes
    16,189

    /UI2/CL_JSON is what we use as per the first link and it works perfectly

    Read only

    Tomas_Buryanek
    Product and Topic Expert
    Product and Topic Expert
    0 Likes
    16,189

    I also vote for /UI2/CL_JSON 🙂

    -- Tomas --
    Read only

    0 Likes
    16,189

    I didn't use /UI2/CL_JSON, because in the second blog, which you mentioned there is an update that using this class is the old technique.

    However, when I replace these lines...

    call transformation zjson_sequence source xml lv_string
                                       result root = lt_data.

    ...in my above report with this:

    /ui2/cl_json=>deserialize( exporting json = lv_string
                                         pretty_name = /ui2/cl_json=>pretty_mode-camel_case
                                changing data = lt_data ).

    then it is still not working, because lt_data is empty after the execution.

    Read only

    DoanManhQuynh
    Active Contributor
    0 Likes
    16,189

    I think to avoid this situation you can use <tt:cond> to check the name, incase field name is fixed...

    Read only

    keremkoseoglu
    Contributor
    0 Likes
    16,189

    You'll find some JSON parsing ideas here: https://blogs.sap.com/2017/08/03/parsing-json-in-abap/