2023 Jul 17 9:48 AM
Hi Folks,
after having problems with the serialize/deserialize methods, I took Sandra Rossi's advice and created some simple JSON-ABAP-JSON transformations. My first ABAP to JSON transformation worked perfectly.
However, I'm having an issue with a very simple JSON to ABAP transformation: it takes a very basic JSON string (3 fields) and converts them to an ABAP flat structure, or tries to.
Here is the JSON string:
{<br>"access_token":"67118f6bfaa1efedba09c90f9b2bc578e70f8468",<br>"expires_in":21600,<br>"token_type":"bearer"<br>}
Here is the target ABAP structure ZSTY_IN_JSON_TOKEN_RESPONSE:
ACCESS_TOKEN Type ZDE_ACCESS_TOKEN STRING 0<br>EXPIRES_IN Type ZDE_EXPIRES_IN STRING 0<br>TOKEN_TYPE Type ZDE_TOKEN_TYPE STRING 0
Here is the transformation:
<tt:root name="ACCESS_RESPONSE" type="ddic:ZSTY_IN_JSON_TOKEN_RESPONSE"/><br> <tt:template><br> <object><br> <str name="access_token"><br> <tt:value ref="access_response.access_token"/><br> </str><br> <str name="expires_in"><br> <tt:value ref="access_response.expires_in"/><br> </str><br> <str name="token_type"><br> <tt:value ref="access_response.token_type"/><br> </str><br> </object><br> </tt:template>
And here's the transformation call (lr_reader TYPE REF TO if_sxml_reader):
CALL TRANSFORMATION zca_in_json_token_response<br> SOURCE XML lr_reader<br> RESULT access_response = ls_response.
Now here's the thing: when I call the transformation, the first field ("access_token") is initialised in the ABAP structure perfectly. The second field ("expires_in") fails every time with the exception CX_ST_MATCH_ELEMENT. The exception error message is "System expected element 'str'".
Maybe it's because the incoming JSON value is numeric, and my structure has a string field as the target? But I have also tried NUMC type (my original choice), integer, decimal and character text for the "expires_in" field. All options fail with the same error.
I suspect the problem lies in this part of the transformation:
<str name="expires_in"><br> <tt:value ref="access_response.expires_in"/><br> </str>
The debugger catches the exception at the first of these three lines, so I expect there's something wrong with it; but I've no idea what.
Thank you for reading, all advice gratefully received.
Cheers
John Moulding.
2023 Jul 17 11:17 AM
2023 Jul 17 12:41 PM - edited 2024 Aug 09 10:07 AM
Here, I reformat the codes in your question (all your codes have <br> inside them) from "Here is the JSON string" up to "And here's the transformation call".
Here is the JSON string:
{ "access_token":"67118f6bfaa1efedba09c90f9b2bc578e70f8468", "expires_in":21600, "token_type":"bearer" }
Here is the target ABAP structure ZSTY_IN_JSON_TOKEN_RESPONSE:
ACCESS_TOKEN Type ZDE_ACCESS_TOKEN STRING EXPIRES_IN Type ZDE_EXPIRES_IN STRING TOKEN_TYPE Type ZDE_TOKEN_TYPE STRING
Here is the transformation:
<tt:root name="ACCESS_RESPONSE" type="ddic:ZSTY_IN_JSON_TOKEN_RESPONSE"/> <tt:template> <object> <str name="access_token"> <tt:value ref="access_response.access_token"/> </str> <str name="expires_in"> <tt:value ref="access_response.expires_in"/> </str> <str name="token_type"> <tt:value ref="access_response.token_type"/> </str> </object> </tt:template>
And here's the transformation call (lr_reader TYPE REF TO if_sxml_reader):
CALL TRANSFORMATION zca_in_json_token_response SOURCE XML lr_reader RESULT access_response = ls_response.
2023 Jul 17 12:46 PM
2023 Jul 17 12:48 PM
You need to understand how SAP converts JSON into JSON XML before it's passed to the XML transformation.
{
"access_token":"67118f6bfaa1efedba09c90f9b2bc578e70f8468",
"expires_in":21600,
"token_type":"bearer"
}
is automatically converted into:
<object>
<str name="access_token">67118f6bfaa1efedba09c90f9b2bc578e70f8468</str>
<num name="expires_in">21600</num>
<str name="token_type">bearer</str>
</object>
THE PROBLEM: your transformation fails because it expects <str name="expires_in"> --- In your below code, use <num ...> instead of <str ...>:
<num name="expires_in">
<tt:value ref="access_response.expires_in"/>
</num>
In case it's not obvious, you may ask ABAP to obtain JSON-XML automatically with this kind of code (ASSERT is just present to show what is obtained):
call transformation id source xml `{"a":1}` result xml data(json_xml) options xml_header = 'no'.
assert cl_abap_codepage=>convert_from( json_xml ) = `<object><num name="a">1</num></object>`.
2023 Jul 17 12:58 PM