Technical Articles
PI REST Adapter – JSON to XML conversion
This blog is part of a collection of blog entries that shows architectural concepts and configuration of the SAP PI REST Adapter. We also added some sample scenarios to make it easier for you to understand how your scenario can be implemented using the PI REST Adapter.
If you haven’t done so far, best is to start with the very first blog PI Rest Adapter – Don’t be afraid within the blog series covering the concepts of the REST adapter. A complete list of all blog entries can be accessed from here PI REST Adapter – Blog Overview.
The current blog shows you along a sample scenario how to convert JSON to XML format and vice versa.
Scenario
A travel agency likes to gather flight details from an airline calling the remote function module BAPI_FLIGHT_GETDETAIL, and expose this interface as RESTful service. The format of the RESTful service should be JSON and hence needs to be converted into XML format before mapped to the BAPI structure.
In the SAP Process Integration Designer perspective of the NetWeaver Developer Studio (NWDS), I have defined an Integration Flow with a REST sender channel, an operation mapping that maps the outbound XML format into the BAPI structure, and an RFC receiver adapter. The conversion from JSON to XML is done within the REST sender adapter.
In the following, let’s focus on how the sender adapter needs to be configured.
Configuring the REST sender adapter
Double-click on the sender channel of type REST, and switch to the General tab below the Adapter-Specific tab. As data format of the input message choose JSON from the drop down menu. Within PI, the format of the payload needs to be XML, so select the Convert to XML check-box.
A sample JSON input message looks as follows:
{
“Agency”: “110”,
“FlightDetails”: {
“AirlineID”: “LH”,
“ConnID”: “0400”,
“Date”: “2014-09-13”
},
}
The two JSON elements Agency and FlightDetails are both on the very first level of hierarchy which is allowed for JSON however not for XML. XML messages can have one root element only. If the JSON payload is converted into XML, this would not comply with the XML specification. So, we need to add a wrapper root element to the converted XML structure. As Element Name and Element Namespace we enter the name and namespace of the message type of our outbound service interface, here flight_query with namespace http://demo/hh/rest/flights.
The scenario runs synchronously, so select Best Effort from the drop down menu of the Quality of Service.
The response of the BAPI call is in XML format within PI, the agency however expects the response being in JSON format. So, we choose JSON as data format of the output message, and select the check box Convert XML Payload to JSON. Furthermore we select the Strip Outer Element check box to remove the message type element from the XML payload.
Switch to tab Channel Selection, and select the Specify Endpoint check box. As custom static endpoint enter /demo/flight.
Switch to the REST Resources tab. Here, we stick to a static endpoint URL, so we just enter / as pattern.
Running the scenario
For testing the scenario you can use the Advanced REST Client Application in the Google Chrome browser. The endpoint URL of your RESTful service starts with http://<host>:<port>/RESTAdapter with host and port of the SAP PI system, followed by what you have defined in the sender channel, here /demo/flight.
Enter a sample JSON payload like the one above, and select the Send button.
The response of the service call provides the flight details such as destinations and schedule in JSON format.
In message monitoring, you can download the payload of the request and response assuming that you have switched on logging. You can see that for the request message the wrapper element, i.e., the message type element has been added.
The response in XML format also contains the message type as root element which is then removed when converted into JSON.
Further XML/JSON conversion rules
From release 7.31 SP17 / 7.4 SP13 / 7.5 SP01 onwards, further XML to JSON conversion rules are supported, see Converting XML/JSON – Advanced Adapter Engine – SAP Library. You can define so called custom XML/JSON conversion rules to overrule the automatic conversion in cases where the result is not as expected, such as forcing an arraytype although an item occurs only once, or changing the data type of an element.
In our specific case, we like to change the message format of the response as follows:
- We like to keep the outer root element, and add a prefix to the same
- The flight element should always be of type array even if it occurs only once
- The connection ID should be of type integer (as you can see above it is interpreted as string)
- The arrival time should be of type decimal; if the conversion fails, a default value should be set
- The duration should be of type string (as you can see above it is interpreted as integer)
So, in the channel configuration, we add the following rules:
- Select the Enable Namespace Mapping check box, and add a new rule. Here, as XML Namespace set http://demo/hh/rest/flights, and as value we simply enter the term Prefix.
- In the Custom XML/JSON Conversion Rules section, add a new rule to define the flight root element as array in any case. Maintain namespace and prefix as seen above in the xml schema, as name set the element name flight, and as array type choose yes. Alternatively, you can also choose 1 or true.
- Add another rule with name ConnID and type integer
- Add another rule with name arrivalTime and type decimal, as default set 12.00 (note, this doesn’t make any sense but I just like to showcase you the default option)
- Add another rule with name duration and type string
If you run the scenario again, the response looks as follows. The respective configuration settings and their impact on the response are highlighted in the corresponding color.
I hope this blog was helpful to understand the JSON conversion capabilities of the SAP PI REST adapter. If you like to learn more, check out the other blogs in the series, accessible from the main blog PI REST Adapter – Blog Overview.
Hi,
We use REST Receiver and convert XML payload to JSON on data format.
If the data has more than 2 records, the data format would be as the following,
{"data":[{"id":"s123","types":11},{"id":"s456","types":22}]}
If the data has only one record, the data format would be as the following,
{"data":{"id":"s123","types":11}}
But our customer's inbound system has to receive the data format, when the data has only one record, as the following,
{"data":[{"id":"s123","types":11}]}
To compare with current format, the array sign, [], is need.
Please help.Thanks.
Hi ZiYu,
I am facing the same issue for single record and unable to find any info to add Array sign in REST receiver adapter. were you able to resolve the same?
Kindly let me know.
Hi both,
There’s a solution to this now: enhanced XML/JSON conversion, also mentioned in the update of this blog above under Further XML/JSON conversion rules. And also see here: https://blogs.sap.com/2016/01/13/rest-adapter-in-sap-pipo-enhanced-xmljson-conversion/
Philippe
Alex, this is amazing !
We struggle 2 problem from customer. When REST adapter convert XML to JSON format , it should refer XSD definition about xml element occurrence, for example above ZiYu 's sample {"data":[{"id":"s123","types":"11"}]}, element "data" we define to 1..unbounded , so "data" element have to convert [ ] for array , no matter there is the single array or multiple value of array. So the result will be the following JSON format :
{"data":[{"id":"s123","types":"11"}]}
And REST adapter has the other issue ,for example the above JSON, if we had define "types" element to xsd:string , cause REST wo't refer XSD definition , so the result convert to integer , {"data":{"id":"s123","types":11}}
That's we found the 2 issues.
Hi Gwendolyn.
We also saw the "11"--->11 convertion problem. Do you know if there is already a solution for that?
Hi,
I am facing same issue of conversion String as Number just because only numbers or decimal in string. Some clues?
Nop. We decided to replace the calls to REST services that had input parameters, with java apps exposed as web services.
hello,
for converting XML like this ...
<CalculationBaseQuantity unitCode="KG">1</CalculationBaseQuantity>
how should be my source JSON format?
Hello Alex
Thanks for writing such descriptive blog, i was able to do my conversion using this and tested several scenarios.
I am facing an issue with a scenario where target system is expecting content type as application/json but Receiver REST adapter with data format as JSON always send the content type as text/plain.
I tried using custom modules but found no way to deactivate the conversion in REST adapter.
To overcome this issue one of the following 2 options should work:
1) To deactivate Data Format conversion ; pls. confirm if I can do this
2) Change the content type of payload via REST adapter ; pls. confirm if I can do this
I am on PI 7.4 SP 14
Thanks
Lalit
Thanks for this great blog. We've got rid of all problems except the custom Rules for mapping. We have 7.40 SP13 but there is no table to maintain the custom mapping rules. Do we have to configure something in addition?
Best guess is that you missed to upload the adapter metadata.
Alex
HI Alexander,
I am having issue with my Sender REST adapter. My requirement is i will be getting a HTTP GET request with 3 variables in the calling URL.
I have defined the REST Resources tab with URL Pattern as '/' and setting the custom attribute using the GET variable.
I am getting issues in retreiving the Dynamic attributes . I cannot see the values in the Runtime as well.
Below are the configuration and JAVA UDF.
JAVA code of UDF
The Dynamic attributes do not show the custom attributes i have defined
Would appreciate if you could help me .
Thanks
Husain
HI Alexander,
I'm having issue with data format in receiver REST adapter which convert XML data to JSON to the external system.It is a string element "remark" valued "abc\ndef" in the payload,but it turned to "adb\\ndef" when the target system gets it. How can i avoid the escape character and just regard '\n' as a pure string?
Would appreciate if you could help me.
Thanks.
Hi All,
I have a scenario (REST–>PI–>REST) wherein PI will receive the data from sender in JSON format. Data format accepted by receiver is also a JSON format.
The input payload to PI looks like:
[{
“ClassCode”: “”,
“FSAC”: “”,
“TrainId”: “”,
“UserId”: “”,
“Equipment”: [{
“EquipmentInitials”: “”,
“EquipmentNumber”: “”,
“EquipmentDisplayType”: ” “,
“SourceId”: “”,
“SourceType”: “”
}, {
“EquipmentInitials”: “”,
“EquipmentNumber”: “”,
“EquipmentDisplayType”: ” “,
“SourceId”: “”,
“SourceType”: “”
}]
}]
When this input is passed to receiver Rest Adapter, I see that PI append root to it which is not acceptable by REST Service.
JSON at receiver adapter looks like below:
{
“root”: [{
“ClassCode”: “”,
“FSAC”: “”,
“TrainId”: “”,
“UserId”: “”,
“Equipment”: [{
“EquipmentInitials”: “”,
“EquipmentNumber”: “”,
“EquipmentDisplayType”: ” “,
“SourceId”: “”,
“SourceType”: “”
}, {
“EquipmentInitials”: “”,
“EquipmentNumber”: “”,
“EquipmentDisplayType”: ” “,
“SourceId”: “”,
“SourceType”: “”
}]
}]
}
How to ignore this root element and add outer Array[], similar to the input payload.
Thanks in advance!!
Best Regards,
Sachin Jangir
Hi Sachin,
I have the same problem. How do you solve this issue?
Thanks in advance!
Best Regards,
Daniel Lafuente
have you guys slove this? I have the same problem now.
I have achived it.
please check:
REST remove root JSON tag in receiver channel
https://answers.sap.com/questions/454329/rest-remove-root-json-tag-in-receiver-channel.html?childToView=456034&answerPublished=true
Hi,
have the same problem. Have you solved this?
Hi Alexander,
i am doing REST adapter Synchronous (REST<–>PI<–>RFC) my scenario working fine. But am facing one issue in chrome i am getting below Waring/error, but response populating correct.
Thanks in Advance for your help.
Best Regards,
Karunakar A
Hi Expert,
I am REST adapter synchronous scenario I am getting csv format response from the target system.
Please guide me how I can receive csv format data in synchronous call using REST adapter.
Thanks in Advance for your help.
Hi,
I would like to know how can I define the Data Type in SAP PO ESR to accept incoming JSON file having Array as top level object. I will use REST sender adapter for this. What I know is that if there's an element above this Array, REST adapter can easily read that element will have multiple occurrences.
[
{
"shipment_number": "473747834", // String
"completedsuccessfully": true, // Boolean
"ProcessingEndtime": "2021-01-29T09:52:14.616Z" // UTC timestamp
},
{
"shipment_number": "798798797", // String
"completedsuccessfully": false, // Boolean
"ProcessingEndtime": "2021-01-29T09:52:14.616Z" // UTC timestamp
}
]
Hi Charles,
actually you need to create a data type with root element and when converting the incoming JSON to XML add the root element, this can be configured in the REST sender channel
Alex
Hi Alex,
I seem to be a little late for the REST / JSON party as this blog now is now entering primary school age 🙂
Anyways I recently had some requirements to consume various REST APIs from SAP Backend via PI / PO (7.50 SP13 in our case).
While it is understandable that "Enable Namespace Mapping" using dot "." a separator for prefix (Prefix.flight :... in your example) by default, is there also a parameter / setting so to change this, say to ":" or completely omit it?
Searched a whole lot in the community and within notes but could not find an easy solution for this.
Thanks / Cheers
Jens