ABAP and JSON
WIth Releases 7.02 and 7.03/7.31 (Kernelpatch 116) JSON is supported natively in ABAP by the following features:
- JSON-XML is a special XML format that enables JSON data to be described using an XML representation. A new format, IF_SXML=>CO_XT_JSON, has been added to the sXML Library, which enables to handle JSON using JSON-XML.
- The canonical JSON representation asJSON defines a mapping between ABAP types and JSON. This is used in serializations and deserializations using the identity transformation ID.
- JSON data can be specified in various forms as an XML source in the statement CALL TRANSFORMATION and a JSON writer can be specified as target. The identity transformation ID supports JSON by using asJSON.
Example:
DATA text TYPE string VALUE `Hello JSON, I’m ABAP!`.
DATA writer TYPE REF TO cl_sxml_string_writer.
DATA json TYPE xstring.
“ABAP to JSON
writer = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
CALL TRANSFORMATION id SOURCE text = text
RESULT XML writer.
json = writer->get_output( ).
“JSON to ABAP
text = `{“TEXT”:”Hello ABAP, I’m JSON!”}`.
CALL TRANSFORMATION id SOURCE XML text
RESULT text = text.
Addendum
Meanwhile, the documentation for ABAP and JSON is online. This blog is pointing to it.
Horst,
thanks for these good news. There already are quite a few ABAP implementations for JSON parsers / builders around, (see for example, my versions here: http://ruediger-plantiko.blogspot.ch/2011/09/ein-json-builder-in-abap.html and here: http://ruediger-plantiko.blogspot.ch/2010/12/ein-json-parser-in-abap.html ). But this implementation in the kernel will clearly be much more efficient.
When I test your ABAP->JSON example above, the xstring JSON will contain JSON-XML. Is there a built-in way to get a "real" JSON string from JSON-XML, or do I have to write an own XSLT transformation to do this?
Regards,
Rüdiger
Hi Rüdiger,
json = cl_abap_codepage=>convert_from( writer->get_output( ) ).
Cheers!
Horst
PS: I guess I did not fully understand the question, but the answer is the same.
In the above example, the xstring JSON does not contain JSON-XML but already the UTF-8 representation of JSON. In order to get JSON-XML, you would have to create an XML writer with cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 ) .
Example:
DATA text TYPE string VALUE `Hello JSON, I'm ABAP!`.
DATA writer TYPE REF TO cl_sxml_string_writer.
DATA json TYPE string.
DATA xml TYPE string.
"ABAP to JSON
writer = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
CALL TRANSFORMATION id SOURCE text = text
RESULT XML writer.
json = cl_abap_codepage=>convert_from( writer->get_output( ) ).
cl_demo_output=>write_json( json ).
"ABAP to JSON-XML
writer = cl_sxml_string_writer=>create( ). "standard type is if_sxml=>co_xt_xml10
CALL TRANSFORMATION id SOURCE text = text
RESULT XML writer.
xml = cl_abap_codepage=>convert_from( writer->get_output( ) ).
cl_demo_output=>write_xml( xml ).
cl_demo_output=>display( ).
gives:
{
"TEXT":"Hello JSON, I'm ABAP!"
}
<asx:abap version="1.0" xmlns:asx="http://www.sap.com/abapxml">
<asx:values>
<TEXT>Hello JSON, I'm ABAP!</TEXT>
</asx:values>
</asx:abap>
More Cheers!
Horst
Hello Horst,
I have a JSON string with deep structure
{
"is_model":
{
"t":"DD",
"i":"Value for DD"
},
"is_qty":
{
"t":"TX",
"i":"2016
},
"is_ctl":
{
"t":"DD",
"i":"Single Apex"
},
"is_ctr_qty":
{
"t":"TX",
"i":"2200"
}
}
I need to convert this to XML for further processing, could you please help me how to get this is XML structure
<object>
<object name="is_model">
<str name="t">DD</str>
<str name="i">Value fo DD</num>
</object>
.
.
.
.
</object>
I you want to do it in ABAP, you can use the sXML library to parse the JSON string and render the result into an XML string.
Hello Horst,
Thanks for the reply, I got it done the way you suggested.
regards,
Purayil
Hi Horst,
Is it possible to convert IDOC Data to JSON format.
If you can transform IDOC to standard XML, you can transform it also to JSON-XML and that means to JSON.
Horst
Hi Horst ,
Thank you for the reply
I am able to convert into XML by using the standard Class cl_idoc_xml1 ,but I am not able to convert to JSON-XML .It would be great if you can help me out in this issue.
Where lies your problem?
Hi Horst,
My requirement is to convert the IDOC data into JSON format for that i tried the following things.
1) Convert the IDOC data into XML Format(by using the standardClass cl_idoc_xml1).Then to JSON Format.At this point of time i am stuck in converting XML to JSON and XML to JSON-XML format .
2) Check for Standard class to convert IDOC data into JSON format.However I didn't find any such class in ABAP.
If there isn't a standard class, you either have to write an XSLT that converts the XML to JSON-XML or to parse the XML into ABAP and render it as JSON-XML.
Hi Horst,
How can I use XSLT to convert XML to JSON in abap.Could you please elaborate ?
HI Kiran,
Please post your query as a question. Remember to post the relevant code section of what you have tried so far.
BR,
Suhas
Hi Suhas,
I had already post the question in SCN .Please find the Post
.By using XSLT to transform XML to JSON-XML ...
Horst,
thank you for your clarifications! Indeed, the writer contains the JSON string, not JSON-XML. I had made an error in my test code.
I also appreciate the support in the debugger! If I look at a JSON string in the "XML Browser" view, I get it nicely transformed into an interactive structured display. Found out that there is an XSLT transformation SJSON2HTML responsible for this nice little feature...
Regards,
Rüdiger
... just for completeness: Here is my test program with 4 tests:
http://pastebin.com/Ey9C5rGd
Regards,
Rüdiger
I have switched my demo application to this new technique, and included a detailled discussion of the built-in JSON parser in the blog: http://scn.sap.com/community/abap/blog/2013/01/24/developing-a-rest-api-in-abap#Using_ABAPs_BuiltIn_JSON_Converter
hello sir , i am new to abap , please help me out how to consume json format webservice in abap.below is the webservice
http://dev.mogocrm.com/a/mogocrm/api/v1/contact/?source=mobile&format=json
Hello,
maybe this is a good place to start:
ABAP Connectivity - Web Services ABAP - ABAP Connectivity - SCN Wiki
You can also try, to do it directly as ishown for html in a very basic example, but that's not too recommended.
Thank you so much sir really its good for basic.
but i already consumed the webservice in my abap but the string is in json format.
i want the output in abap.
Hello Horst,
the information about the prerequisites about the sap system is nor precise enough. We drive 7.02 with dbsl patch level 314 and sp 06: because the corresponding interfaces and classes does not recognize the type if_sxml~co_xt_json.
I have repaired IF_SXML and CL_SXML_WRITER and it works.
Regards, Stefan
Hi Stefan,
I'm facing the same issue. Can you please eloborate on what you did to fix the issue. You stated that you have repaired the classes. How did you repair them?
Thanks,
Karthik
There is a SAP Note 1648418 with correction instructions.
Hi Horst,
Thanks for your response. That note is not compatible with our instance of SAP. The problem that I'm facing is, I'm getting a dump during the execution of the statement
cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
I'm getting the dump for the exception CX_SXML_INTERNAL_ERROR, and only for the type IF_SXML=>CO_XT_JSON and not for other 3 types.
Any help is appreciated.
Thanks,
Karthik
Hi Kathrik,
JSON support is possible in the basis releases described in note 1648418 if you run on the 7.20-kernel described in note 1650141.
From the error I guess that you have the right ABAP release but not the right kernel release.
Best
Horst
Hi Horst,
Thanks for your reply.
Our instance of server:
I checked importing the notes but SNOTE throws that the notes cannot be implemented. Please help me regarding this.
Thanks,
Karthik
Hi Stefan,
I'm also interested in how to "repair" these classes. Do you mean one has to activate some "hidden" stuff or reimplement missing functionality?
Thanks.
Alexander
There is a SAP Note 1648418 with correction instructions.
Hello Horst,
I would like to Display the Json like XML in an SAP-Browser:
http://scn.sap.com/thread/3341060
It is possible or should I develop an own Vizualisation?
Best regards,
Damir
Hi Damir,
see my answer to your thread.
Best
Horst
Horst,
I am now trying to understand how references are handled. I saw that the references need to have a built-in or DDIC type - not a local or adhoc type - otherwise XSLT throws a "technical error" (which could be surpressed with "options technical_type = 'ignore'", but the corresponding data object would be ignored).
I have a table of named references of arbitrary data objects (actually, I defined this type as a DDIC type, but I write it here as if it were a local type):
types: begin of ty_data,
name type string,
value type ref to data,
end of ty_data,
ty_data_tab type hashed table of ty_data_tab,
and pass it to an XSLT transformation
data: lt_data type ty_data_tab.
call transformation zdata
source
data = lt_data
result xml lo_json.
The transformation should dereference these data, the result being a hash of named data:
{ "name1": ... the JSON representation of data object name1 here ...,
"name2": ...
}
The only solution I currently see is to do the derefencing in ABAP using the ->* operator, to call the identity transformation in a loop for each dereferenced data object, and to compose the enclosing JSON object from these parts manually.
Or is there a way to do this dereferencing inside of an XSLT transformation? This would open the way for mixing the built-in canonical transformation ABAP->JSON with own templates inside of an XSLT transformation. Which would be much more elegant and efficient than the "solution" calling N times the identity and doing string concatenation in ABAP.
Regards,
Rüdiger
Hi Rüdiger,
An XSL-transformation always transforms from XML to XML. What you have to know, is the format of the XML data, your XSL-transformation works with.
ABAP-Source:
If you use CALL TRANSFORMATION with an XSL-transformation in order to transform ABAP data, the trick is that the ABAP data are always serialized into asXML and that the XSL-transformation works with that format, i.e. you must write a transformation that handles the asXML data.
JSON-Target:
Now for JSON. XSLT does not know JSON. Here, the trick is that there is a SAP-specific mapping from XML to JSON called JSON-XML. If you specify a JSON-writer as target of CALL TRANSFORMATION, the XSLT must produce JSON-XML that is then transformed to JSON by the writer.
Putting it together:
Your XSLT accesses the asXML representation of the connected ABAP data and must transform it to JSON-XML.
So, as first step, call transformation ID for your ABAP data with an XML target in order to examine the asXML data that you have to handle. Then write an XSLT that transforms these asXML data to the JSON-XML that represents the JSON data you want to achieve. Applying that XSLT to your ABAP data with a JSON-writer as target gives the desired result.
For information about JSON-XML see http://scn.sap.com/people/horst.keller/blog/2013/04/11/json-xml-saps-xml-representation-of-json
Best
Horst
Horst,
thanks for your answer. Of course, XSLT maps XML to XML. I knew that.
In my question, the source was ABAP data, which means that the XML source format is asXML implicitly.
Also, in my question, the target format was a lo_json string writer, which means that the target XML format is implicitly asJSON. So I am speaking of an XSLT transformation asXML to asJSON. So the XSLT transformation will produce a tree consisting of <object>, <str>, <array> ... elements and the like.
It is not necessary, as you wrote, that I first have to call the identity transformation explicitly, and in a second transformation to map the XML to JSON. Instead, I can directly work in one and only one XSLT transformation on the ABAP data, assuming them in asXML notation, and I can directly in this same XSLT transformation produce an asJSON XML output. This works fine in the non-reference case, and I have already developped various transformations of this type.
My only problem is with data references. Let me give you a simple example.
When you run the following test with a sample concrete "ref to" data object,
method test.
data: lo_json type ref to cl_sxml_string_writer,
lt_t000 type ref to cts_t000_tab,
lv_json type xstring.
create data lt_t000.
select * from t000 into table lt_t000->*.
lo_json = cl_sxml_string_writer=>create( if_sxml=>co_xt_json ).
call transformation id
options
data_refs = 'heap-or-create'
source
data = lt_t000
result xml
lo_json.
lv_json = lo_json->get_output( ).
break-point.
endmethod.
Then you get the following JSON output:
{
"DATA": { "%ref": "#d1" },
"%heap": {
"d1": {
"%type": "dic:CTS_T000_TAB",
"%val": [
{
"MANDT": "000",
"MTEXT": "SAP AG Konzern",
"ORT01": "Walldorf",
"MWAER": "EUR",
"ADRNR": "",
"CCCATEGORY": "S",
"CCCORACTIV": "2",
...
Actually, the impicit XML asJSON output is
<?xml version="1.0" encoding="utf-8"?>
<object>
<object name="DATA">
<str name="%ref">#d1</str>
</object>
<object name="%heap">
<object name="d1">
<str name="%type">dic:CTS_T000_TAB</str>
<array name="%val">
<object>
<str name="MANDT">000</str>
<str name="MTEXT">SAP AG Konzern</str>
<str name="ORT01">Walldorf</str>
... and so on
So the ABAP->JSON converter is able to deserialize the data and to produce the fragment
<object>
<str name="MANDT">000</str>
...
and so on.
I am looking for an XSLT transformation ZDATA which produces the actual data to which the reference points, in a generic way, i.e. independent of the actual data type. (So I want to dereference the data object inside of the XSLT transformation.) In the example, I want to produce as part of the result the following JSON array
[
{
"MANDT": "000",
"MTEXT": "SAP AG Konzern",
"ORT01": "Walldorf",
"MWAER": "EUR",
"ADRNR": "",
"CCCATEGORY": "S",
"CCCORACTIV": "2",
...
].
Of course, as you proposed, I could evaluate the asABAP XML source fragment located below the asx:heap node (given by the XPath expression /asx:abap/asx:heap/*[@id = substring(./@href,2)] where the current node in asx:data is of reference type).
But then I should explicitly program the cases: Is this a table, a structure, a simple data object? Or is it nested (if yes: do recursion...)? And all this logic has obviously already been implemented in the ABAP -> JSON converter: As you see in the example, the %val element of the heap section already contains what I am looking for.
I hope that I could explain more clearly what I am looking for.
Thanks for having a second look at this.
Regards,
Rüdiger
Hi Rüdiger,
You say:
"Also, in my question, the target format was a lo_json string writer, which means that the target XML format is implicitly asJSON. So I am speaking of an XSLT transformation asXML to asJSON."
No, that is not the case. When using a JSON writer as a target format, the target XML format is not implicitly asJSON. The target format can be any JSON-XML and your transformation defines how to create it. asJSON is produced by the predefined transformation ID and you only see it when using transformation ID. If you use transfromation ID to serialize ABAP data to a JSON writer, conceptually first asXML is produced, second this is converted to asJSON-XML and third this is passed to the JSON Writer. In reality this is done in one step. But asJSON is generally not needed for self-written transformations, where you have to work with JSON-XML instead.
You say:
"It is not necessary, as you wrote, that I first have to call the identity transformation explicitly, and in a second transformation to map the XML to JSON."
I didn't want to say that. What I wanted to say is that you have to look at the implicitly created asXML first and write an XSLT that converts that XML to the JSON-XML that you want to have. Of course you don't need this intermediate step later on.
You say:
"And all this logic has obviously already been implemented in the ABAP -> JSON converter".
Sure, asJSON defines a mapping of all ABAP types to JSON including reference variables. For the asJSON representation of anonymous data objects and class instances (objects), which are addressed using references in reference variables, a reference mechanism is used like in asXML. Since JSON does not has any syntax for references, an SAP-specific reference mechanism based on asXML is used, where named reference variables are displayed as object components, whose content is a key for the referenced objects and the referenced objects are stored as object components in the object %heap.
But this is the predefined ABAP to JSON mapping! What you want to achieve is a selfdefined ABAP to JSON mapping including a derserialization and for this, you must either evaluate the asXML in your transformation yourself or deserialize the ABAP data before transforming them.
Best
Horst
Horst, I have used the wrong term, sorry for that. The target format of a transformation with a JSON writer as recipient is an XML dialect consisting of <object>, <array>, <str>, ... elements. I wrongly thought the name for this dialect would be asJSON. As you corrected, this was the wrong name. Let's call it SAP-JSON-XML.
So I understand your reply that, unfortunatly it's not possible to reuse the code which maps asXML ABAP data (is this the right name? Please don't be angry with me if it's the wrong name, you know what I mean) to the canonical SAP-JSON-XML tree fragment in custom XSLT transformations.
Thanks for the answer anyway.
Regards,
Rüdiger
Hi Rüdiger,
To my knowledge you cannot reuse the internal (kernel) functions that create asJSON from ABAP data. It is the same as for XML. There, you can also not reuse the (kernel) functions that create the asXML that is used implicitly or explicitly (when using ID).
Kind regards
Horst
Very interesting blog , thank you!
one question :
in JSON to ABAP
text = `{"TEXT":"Hello ABAP, I'm JSON!"}`.
CALL TRANSFORMATION id SOURCE XML text
RESULT text = text.
I don't need to specify that XML source is a JSON string , does it recognize just parsing the string?
thank you
Alessandro
Yep!
Currently I am preparing a general blog about ABAP and XML, where I mention this. ...
Horst,
I wonder how to convert ABAP to Booleans:
How can i produce the JSON object
{ "FLAG": true }
from ABAP data. Is there a special data type which will be interpreted as Boolean? I can only produce
{ "FLAG" : "X" } ( using data element FLAG for the component FLAG)
and
{ "FLAG" : "true" } (using elementary data type STRING for the component FLAG)
which is not what I want.
Thanks for an answer.
Rüdiger
Hi,
ABAP does not have a Boolean type. Therefore, transformation ID that produces asJSON cannot produce a JSON Boolean directly.
Option 1:
There is a JSON-XML representation for JSON Booleans:
Boolean values
true → <bool>true</bool>
false → <bool>false</bool>
http://scn.sap.com/people/horst.keller/blog/2013/04/11/json-xml-saps-xml-representation-of-json
You have to write or use a transformation that converts the asXML of ABAP_BOOL into the above JSON-XML.
Option 2:
Use the domain XSDBOOLEAN (http://help.sap.com/abapdocu_731/en/index.htm?url=abenabap_xslt_asxml_schema.htm ). ABAP values typed with with data types of that domain are represented as real JSON Booleans when converted to JSON with ID.
Example:
DATA:
BEGIN OF boolean,
ab_true TYPE abap_bool
VALUE abap_true,
ab_false TYPE abap_bool
VALUE abap_false,
xsd_true TYPE xsdboolean
VALUE abap_true,
xsd_false TYPE xsdboolean
VALUE abap_false,
END OF boolean.
DATA(writer) = cl_sxml_string_writer=>create(
type = if_sxml=>co_xt_json ).
CALL TRANSFORMATION id SOURCE boolean = boolean
RESULT XML writer.
DATA(json) = writer->get_output( ).
Best
Horst
Horst,
thanks for the answer. The XSDBOOLEAN type is a practical option, it saves you the work of writing an own transformation, you can use the identical transformation instead. It works well on our SAPKB70211 system, as I just tested.
Thanks & regards, Rüdiger
Hi Horst,
is there a way to keep the internal ABAP representation of datatypes when transforming them?
I have the use case that the user must be able to see how the values will look like in ABAP.
E.g. 'true' should be an 'X'; Date shold look like '20130701' and not like '2013-07-01'.
Kind regards
Stefan
Hi Stefan,
If you use the predefined transformation ID (see http://help.sap.com/abapdocu_740/en/index.htm?url=abenabap_json_trafo_id.htm ), you automatically work with asJSON (see http://help.sap.com/abapdocu_740/en/index.htm?url=abenabap_asjson.htm), where each ABAP type is mapped to a predefined JSON representation. With some special domains you can influence the mapping (see http://help.sap.com/abapdocu_740/en/index.htm?url=abenabap_asjson_schema.htm). If those don't help, you have either to choose another ABAP type or write your own XSL or ST transformation.
Best
Horst
Ohkay, after direct communication, we learned that above suggestions do not really help.
The task is to transform character-like data objects (especially d and t) as if they were strings.
For the moment, the best way seems to be to create an intermediate ABAP data object where all character types are replaced by strings (using RTTS), assign the original object to the new one and to transform that one.
Maybe there are better ideas?
Thanks for confirming my assumptions!
Hi Horst,
Ours is 7.01 version.We are able to do the conversion between ABAP and JSON by applying the note you have provided in the thread. Now, we want to represent the JSON data to a byte-like representation in accordance with a code page.But the class : CL_ABAP_CODEPAGE is not available in our system .Due to that we are not able to achieve it .For achieving this in 7.01 system ,Is there any SAP note available for consuming the class : CL_ABAP_CODEPAGE from 7.01 ? or anyother alternative ways there?
Thanks,
Selva.
Hi Selva,
CL_ABAP_CODEPAGE is a convenience class that encapsulates other classes (see docu). Before 7.02 you can (or must) use these classes directly.
Best,
Horst
Horst, in your example for JSON to ABAP, it seems that the variable text is only filled with data if the JSON field "TEXT" is uppercase. Is there a way to ensure that the transformation also works for mixed case JSON fields, such as "someText" and "Text"?
You are not the first one who asked.
As an answer I've written an example for that use case ....
😎
PS: DEMO_JSON_XML_TO_UPPER used in the example looks as follows:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="name">
<xsl:value-of select="translate(., $smallcase, $uppercase)"/>
</xsl:attribute>
</xsl:template>
</xsl:transform>
Thanks a lot, Horst, that saved me lots of time 🙂
Here is the code, I am looking for a field called "message" in the JSON:
I was thinking it might also be possible to use the parameter table of type ABAP_TRANS_PARMBIND_TAB, but that did not work out.
I tried that too before writing the workaround 😛
My idea would be to offer an appropriate transformation option
that ignores the case of names. But up to now, my development buddies have not implemented it ...
Yeah, that would make even more sense - JSON in ABAP is great (in 7.4 at least), but this particular thing is a weak spot. This is the kind of thing that my web developer friends make fun of 🙂
"But up to now, my development buddies have not implemented it ..."
With good reasons, I think. This would be half-baked. Think of the way back. How should ABAP know how to convert upper case to mixed? lower? case.
Use transformations. A mapping of element names is already available, there is no need for further development: in the form of own transformations, you can customize your mapping in whatever way.
And mapping only names is quite easy.
Regards,
Rüdiger
My development buddy, in fact the master mind behind all the modern ABAP stuff (XML, JSON, expression enabling, ...), told me that Rüdiger's answer is right one. Chapeau!
And that's about that ...
PPS: Someone who knows SAP-XML better than me (the master mind, see above) told me, that the transformation can be written shorter as follows:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sap="http://www.sap.com/sapxsl" version="1.0">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:attribute name="name">
<xsl:value-of select="sap:upper-case(.)"/>
</xsl:attribute>
</xsl:template>
</xsl:transform>
Hi Horst,
I am still a little new to simple transformations, but I have created some ABAP based restful APIs that consume and produce JSON for Javascript Web based applications and use simple transformations to deserialize the JSON to ABAP.
One thing that is troubling me. As I understand it, you cannot guarantee the order that javascript object properties will be output during serialization to JSON. More often than not they are processed in the order they were added to the object, but it should be assumed that the order is not guaranteed and it is down purely to the browser specific implementation.
As for the simple transformations, as far as I can see, it is expected that the XML nodes must appear in the order that they are to be parsed.
If we cannot guarantee the order in which each browser implementation will serialize the Javascript Object to JSON, how can we handle that in the simple transformation.
I'm struggling to find a solution, but thought I'd throw this out there in case any following this has come across the same issue and has any thoughts on the topic.
Thanks,
Katan
From the JSON standard: http://www.ietf.org/rfc/rfc4627.txt
So the order of object members cannot be guaranteed. This is in sync with the ECMAscript specification for object members: No guaranteed order. It's only by chance if the implementors give you the order that you were expecting. You cannot rely on it, if you want to write robust software.
From your description, I do not understand why you need this order. If you have good reasons for this, you'll have to work with an array of objects instead, with other words you'll have to change the JSON data structure.
Regards, Rüdiger
Hi Rudiger,
This is exactly my point. As I said before, object properties are unordered, but Simple Transformations expect order (unless I am mistaken and I hope I am).
In cases where you need to conform to a standard (i.e. GeoJSON GeoJSON Specification ), you cannot just switch an object to be an array (to guarantee order) or you deviate from the standard.
It seems a fairly rudimentary thing to process things out of order to deal with deserializing object properties to ABAP, but perhaps I am wrong.
Regards,
Katan
Hi Katan,
In simple transformations, you do not address only by order but also by using names (see http://help.sap.com/abapdocu_740/en/index.htm?file=abenst_addressing_current_node.htm).
This is especially the way for deserializing into structures (that are represented as unordered objects in JSON). See http://help.sap.com/abapdocu_740/en/index.htm?file=abenst_tt_value_structure.htm.
So if you take the example from http://help.sap.com/abapdocu_740/en/index.htm?file=abenabap_st_json_table_abexa.htm, you can deserialize the JSON string also into an internal table where the components of the table line have another order, because its the name that counts and not the order.
DATA: BEGIN OF carrier_wa_new,
carrid TYPE scarr-carrid,
url TYPE scarr-url,
carrname TYPE scarr-carrname,
END OF carrier_wa_new,
carrier_tab_new LIKE TABLE OF carrier_wa_new.
CALL TRANSFORMATION demo_st_json_table
SOURCE XML json
RESULT carriers = carrier_tab_new.
Hope this helps.
Horst
The mastermind (the master of it all, see above) tells me, that the correct answer is to use tt:group.
Hi Horst,
Thanks for that. I realised I was using the <tt:cond> without <tt:group>, which kind of worked. But following the documentation in the link you posted, it's now working perfectly. I can control the occurences using "frq" and by nesting my group statements I can control things better for more complex scenarios using nested objects and arrays.
Uwe - Thanks for letting me know about the id transform, I did not know that. I spent some time trying to parse a JSON object with an array property using the "id" transformation with little success. The example you created worked fine for object properties, but I could not get it to work using array elements
I created the following simple example based on JSON arrays being translated to ABAP tables, but without any joy. I'm obviously missing something, but I can't see anything in the help, to indicate what that may be...
TYPES: BEGIN OF ty_num,
num TYPE string,
END OF ty_num,
tty_nums TYPE STANDARD TABLE OF ty_num.
START-OF-SELECTION.
DATA: test TYPE tty_nums,
json TYPE string.
json = '{"nums":[123,456]}'.
CALL TRANSFORMATION id SOURCE XML json
RESULT nums = test.
Thanks for your patience guys...
Thanks,
Katan
Hi Katan,
Please be aware, that working with ID always means working with asXML/asJSON, see
Identity Transformations for JSON and asJSON.
If you want to deserialize JSON directly with ID into ABAP, the JSON must be in the asJSON format that matches the target ABAP data objects.
JSON objects -> ABAP structures
JSON arrays -> ABAP internal tables.
The JSON format in your above example simply is not valid asJSON for the target object. It must be
{
"NUMS":
[
{
"NUM":"123"
},
{
"NUM":"456"
}
]
}
(your table line is structured and therefore, you must have an object for the structure component inside the array).
JSON-data as well as XML-data that are not in asJSON/asXML format must be transformed into that format before deserializing. That's exactly what you have to do when working with XSLT. When deserializing any JSON/XML with XSLT, the result of the transformation must be asJSON/asXML that is then so to say further deserialized into the ABAP objects implicitly by ID. -> Direct execution of ID only possible for asJSON/asXML.
With Simple Transformations, there is no ID involved. The mapping between JSON/XML and ABAP data objects is done directly, because that's the only purpose of ST. XSLT in contrast is a general language where ID and asJSON/asXML have to be introduced in order to connect to ABAP (see also "Serializations and Deserializations" in ABAP and XML – Wrapping it Up).
Best
Horst
And to your initial question: it works, the JSON transformation is working like a move-corresponding.
Useful addition for the special case of the identical transformation!
I already thought nobody would ask about or mention the prdefined transformation ID regarding the order of structure components in JSON.
But here it is and I can point to that documentation too 😉 :
http://help.sap.com/abapdocu_740/en/index.htm?file=abenabap_asjson_abap_types_struc.htm
You see, the reason is the asJSON that is consumed by the Identitiy Transformations for JSON in the example above.
But Katan was originally asking about Simple Transformations that are always self-written, not predefined. Those don't need asJSON. One shouldn't mix those things up.I have written a blog ABAP and XML – Wrapping it Up, that summarizes these facts for XML. For JSON it's quiet similar.
Rüdiger, someone took it upon themselves to delete our whole exchange about missing attribute names in JSON-XML, but thanks for your help clearing up that issue.
I have no idea what kind of moronic moderator would remove extremely useful content. This is the kind of incident that makes we wish we were all using StackExchange instead.
-frank
Hi Frank,
that's disappointing news 😡
The deleted discussion was not only helpful, but other users might take advantage of it also when google'ing for a solution to their problem.
For the records (for the problem Googlers): You had written an ST transformation to map between an ABAP structure and a JSON string, which happened to work only one way: from JSON into ABAP. The other way round, it dumped. The cause was that the produced XML document was not conforming to the rules of JSON-XML (in this case the rule: children of <object> elements must have a name attribute). After fixing this, the ST worked both ways as intended. I added a link to my blog A Validator for JSON-XML
and the online JSON-XML validator tool exposed therein ( A JSON-XML validator ).
Regards,
Rüdiger
P.S.: I've made a copy of this text for further reuse if necessary.
For completeness, here is my transformation:
and here is my JSON:
As Rüdiger pointed out, this would successfully convert JSON to ABAP structure, but it would not convert ABAP structure to JSON because some nodes are missing the name attribute. The second node from the top is missing name="MarkedWorkLocation", the array is missing name="Locations", and the second object inside the array is missing name="latLang".
Hi Frank,
now i am trying to convert json to abap . my JSON data is similar to above JSON data which you mentioned. Can you please give me a suggestion to solve convert that json into ABAP.
Thank you!
Hi Venkatesh,
My Json structure also is same as above but the program is going to dump!
if u r is resolved plz help me.
Thank You.
That would be me 🙁
Someone had reported an abuse for that & tbh i was wondering why would you (of all people) get reported. But i should have listened to my instinct to check the content before deleting it. My apologies!
Do you have any details of the content you had posted so that i can ask the SCN support team to reinstate it. 😐
Sorry for the inconvenience.
BR,
Suhas
PS - That's why i don't like to moderate while in the middle of doing something
Hi Suhas, sorry about the harsh wording, good of you to step forth 😀
I can reply to Rüdiger's post above with my original post (I have a copy) and also include Rüdiger's explanation for the error. I think I'll also sum up the learnings from these blog comments in a blog of it's own when I get around to it.
thanks
Frank
Hi Suhas,
thanks for your reply. I appreciate that you wrote this message.
I hope that I don't have a "spammer" image in the meantime, due to my vivid (a.k.a. garrulous) comments in the SCN 🙂
Frank's question would admittedly have been better placed in the ABAP development discussion area, but I don't see the point in deleting it if it happens to be answered here.
Regards,
Rüdiger
You are one of the few who keep the forum standards high. Your level of knowledge & expertise is second to none.
So no way you fall in the "spammer" category 😛
Now i remember the sequence of events. Someone reported that it was not a blog & i did not X-check once before rejecting the content. My bad!
That would be me 🙂
I think that transformation and resolution will help the community better if it is present as a solved question in forums.
It often happens that questions asked in blog comments get rejected.
Hello Horst,
When trying to unmarshall deep JSON documents where all the keys are in lower case (I think represents multitudes of use cases), the transformation becomes problematic. Using (rtab) can only get you so far, and then arrays are still an issue.
It would be nice if there were at least an option to interpret the keys in the JSON document in a case-agnostic way so that they map to ABAP fields automatically.
Regards,
Martin
Hello Martin,
did you observe that the upper/lower case topic has been discussed extensively in the discussion thread to this blog?
I see two cases here:
So such an option "ignore-case" would be of very limited help in practice.
Regards,
Rüdiger
Hello Rüdiger,
Thanks, I suppose I should have scanned through the discussion to see whether this topic had been covered 🙂
It is unfortunate that there is no easy way to handle JSON data in ABAP in spite of these advancements. (Depending of course on what one deems "easy"; writing transformations in addition to defining the data structures sounds like a lot of work to me).
I suppose there is still scope for writing a custom parser/mapper to cater for some cases.
Regards,
Martin
Hi Martin,
There are lots of custom parsers already out there in the wild (exactly for this reason).
One of them: Usage zJSON · se38/zJSON Wiki · GitHub
Thanks Uwe. I have recently written another JSON parser again to meet my specific needs, which I have documented here: Yet another ABAP JSON parser
I have multiple structures and I need to convert them into JSON. How it's possible to perform nested JSON Formatting in ABAP. The scenario which I am planning to build is there are 4 structures and need to send the data in JSON format using HTTP request. Any guidance or help would be appreciated.
Pratik
if there is a slash in the field name, it comes back as in a different format.
Example:
Input field name : /company/code
output : _-company_-code
I couldn't find a way to bring back it as original.