Having problems with JSON to ABAP. This is a highly simplified example but tries to capture the main point. Each and every JSON element (with few exceptions) could be present with a real value, present with a null value, or not present at all.
In this example there are 3 order items. An order item may or may not have an order_reason. For line 01 it is ABC, for line 02 it is null and for line 03 it is not present at all.
If you look at the XML you can see that the element created varies depending on the content and I don't know how to deal with that in my ST. I guess it is some kind of condition or group or switch, but I cannot seem to find the right syntax to check whether a element is sometimes "null" or sometimes "string". It is therefore not a check on the content of the element but the actual element itself.
Super-Simple JSON
{
"order_id": "564320",
"items": [
{
"line": "01",
"order_reason": "ABC"
},
{
"line": "02",
"order_reason": null
},
{
"line": "03"
}
]
}
This is then implicitly converted to XML for processing in the ST. Order Reason element is <str...> for the first item, and then <null ....> for the second, and missing in the last line.
<object>
<str name="order_id">564320</str>
<array name="items">
<object>
<str name="line">01</str>
<str name="order_reason">ABC</str>
</object>
<object>
<str name="line">01</str>
<null name="order_reason" />
</object>
<object>
<str name="line">03</str>
</object>
</array>
</object>
Here is my example ST.
<?sap.transform simple?>
<tt:transform xmlns:tt="http://www.sap.com/transformation-templates" >
<tt:root name="ROOT" />
<tt:template>
<object>
<str name="order_id">
<tt:value ref="ROOT.order_id"/>
</str>
<array>
<tt:loop ref="ROOT.items">
<object>
<str name="line">
<tt:value ref="$ref.posnr"/>
</str>
<str name="order_reason">
<tt:value ref="$ref.reason"/>
</str>
</object>
</tt:loop>
</array>
</object>
</tt:template>
</tt:transform>
Here is an executable ABAP to test the above. There are two version of the JSON to test. The first works, because each item has a reason code. Check this just to make sure that everything is working in the happy-case. By switching to the second example in the code you can see that there needs to be something to deal with the <null ....> element instead of the <str ....> element. So not the content of the element, but the expected element itself. I tried to do an existence check on the element <str ...> but that did not seem to work (or actually I don't know the syntax for referencing the type / name of the current element).
*&---------------------------------------------------------------------*
*& Report Z_JSON_ABAP
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT z_json_abap2.
CLASS demo DEFINITION.
PUBLIC SECTION.
CLASS-METHODS main.
ENDCLASS.
CLASS demo IMPLEMENTATION.
METHOD main.
TYPES: BEGIN OF ty_s_line,
posnr TYPE posnr,
reason TYPE char3,
END OF ty_s_line.
TYPES: BEGIN OF ty_s_header,
order_id TYPE vbeln,
items TYPE TABLE OF ty_s_line WITH DEFAULT KEY,
END OF ty_s_header.
DATA: lt_order TYPE ty_s_header.
* Example 1 - Works - Easy!
DATA(lv_json) = cl_abap_codepage=>convert_to(
`{` &&
` "order_id": "51324", ` &&
` "items": [ ` &&
` { ` &&
` "line": "01", ` &&
` "order_reason": "ABC" ` &&
` }, ` &&
` { ` &&
` "line": "02", ` &&
` "order_reason": "DEF" ` &&
` }, ` &&
` { ` &&
` "line": "03", ` &&
` "order_reason": "123" ` &&
` } ` &&
` ] ` &&
` } ` ).
* Example 2 - Does not work! - Swap sections to test
* DATA(lv_json) = cl_abap_codepage=>convert_to(
* `{` &&
* ` "order_id": "51324", ` &&
* ` "items": [ ` &&
* ` { ` &&
* ` "line": "01", ` &&
* ` "order_reason": "ABC" ` &&
* ` }, ` &&
* ` { ` &&
* ` "line": "02", ` &&
* ` "order_reason": null ` &&
* ` }, ` &&
* ` { ` &&
* ` "line": "03" ` &&
* ` } ` &&
* ` ] ` &&
* ` } ` ).
CALL TRANSFORMATION zst_order_test SOURCE XML lv_json RESULT root = lt_order.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
demo=>main( ).