2018 Oct 18 4:31 PM
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:
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é
2018 Oct 18 7:51 PM
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
I think the issue with the boolean might be fixed, but not sure, because it's a while ago I used it (first link).
2018 Oct 18 6:58 PM
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>
2018 Oct 19 12:54 PM
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é
2018 Oct 19 1:16 PM
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.
2018 Oct 18 7:51 PM
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
I think the issue with the boolean might be fixed, but not sure, because it's a while ago I used it (first link).
2018 Oct 18 10:13 PM
/UI2/CL_JSON is what we use as per the first link and it works perfectly
2018 Oct 19 7:18 AM
2018 Oct 19 12:46 PM
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.
2018 Oct 19 1:30 AM
I think to avoid this situation you can use <tt:cond> to check the name, incase field name is fixed...
2018 Oct 19 1:41 PM
You'll find some JSON parsing ideas here: https://blogs.sap.com/2017/08/03/parsing-json-in-abap/