Azure APIM : Convert JSON Response to Customized XML Format - json

I have a requirement where I want to convert the JSON response , which is an array of object , to the customized XML format , so that my already existing code can parse it.
I know there is a Azure Transformation Policy named <json-to-xml /> , but there is no customization possible with it.
Sample JSON Response:
{
"data":[
{"a":1,"b":2},
{"a":3,"b":4}
],
"param2": "Success",
"param3": "true"
}
Desired XML Format:
<result>
<sub-res>
<res x="a" y=1>
<res x="b" y=2>
</sub-res>
<sub-res>
<res x="a" y=3>
<res x="b" y=4>
</sub-res>
</result>
I have tried using the liquid template as well but no success. Need guidance or pointers on this.

For this requirement, I created an api which response {"data":[{"a":1,"b":2},{"a":3,"b":4}]} to simulate your situation.
Then I use a <json-to-xml> in APIM policy first, the response will be convert to xml shown as below after the <json-to-xml> policy:
<Document>
<data>
<a>1</a>
<b>2</b>
</data>
<data>
<a>3</a>
<b>4</b>
</data>
</Document>
After that, use xslt to convert the xml to which you want.
Below is all of policy in my APIM for your reference:
The result of APIM show as what you want:

Related

Map file in the Integration for the LogicApp in Azure

Have the following XML as a result of the HTTP GET function from the B2B supplier.
<Invoices xmlns="http://gateway.com/schemas/Invoices" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://gateway..com/schemas/Invoices Invoices.xsd">
<DocumentInfo>
<DocType>INVOICES</DocType>
<DocVersion>2.0</DocVersion>
</DocumentInfo>
<Header>
<StartDate>2018-12-01T00:00:00+01:00</StartDate>
<EndDate>2019-01-03T00:00:00+01:00</EndDate>
</Header>
<Documents>
<Invoice InvoiceId="RP82807" InvoiceDate="2019-01-02T00:00:00+01:00" DocumentType="IN" RefDocId="FT34532" RefDocType="ORDER" SystemId="10" HasPDFImage="0" />
<Invoice InvoiceId="T609881" InvoiceDate="2018-12-31T00:00:00+01:00" DocumentType="IN" RefDocId="FT39339" RefDocType="ORDER" SystemId="0" HasPDFImage="0" />
</Documents>
</Invoices>
Based on this article I've created the liquid map file to get the list of InvoiceIds:
{
"Invoice": "{{content.Documents.Invoice}}"
}
When using it in the LogicApp in the XML->Json converter, got the following result:
{
"Invoice": ""
}
I have also tried this as a liquid file:
{
"Invoice": "{{content.Invoices.Documents}}"
}
and this:
{
"Invoice": "{{content.Invoices.Documents.Invoice}}"
}
with the same result.
Can you give me a tip what I do wrong?
I tried to transfer part of your xml file to json with this map:
{
"DocType":"{{content.DocumentInfo.DocType}}",
"Invoice":"{{content.Documents.Invoice}}"
}
And get the output:
{
"DocType": "INVOICES",
"Invoice": ""
}
So this means I can get the DocType but can't get Invoice properties, so I think maybe the Liquid map doesn't support the XML format. Maybe you could change it to like this:
<Invoice>
<InvoiceId>T609881</InvoiceId>
<InvoiceDate>2018-12-31T00:00:00+01:00</InvoiceDate>
<DocumentType>IN</DocumentType>
<RefDocId>FT39339</RefDocId>
</Invoice>
This will work, or you could go to Liquid reference to check is there any methods to match the properties.
Note:what you want for now,binding to Xml Attributes is not currently supported.You could refer to this answer.
If you still have other questions, please let me know.
UPDATE:You still could do it with logic app. For example I used a FTP connector to get xml file content then create a json with "json(xml(body('Get_file_content')))" expression.
And this is the result.

how can I loop over json payload received by wso2 esb proxy-service

I'building a proxy-service using wso2 esb. It sends a REST request to Google Books API and receives json. In this Json, there's a dynamic array which I have to parse to XML. I can't seem to figure out how can I do that.
received json payload
"items": [
{
"volumeInfo": {
"title": "Web Services",
"authors": [
"Gustavo Alonso",
"Fabio Casati",
"Harumi Kuno",
"Vijay Machiraju"
],
"publisher": "Springer Science & Business Media",
"publishedDate": "2003-09-04"
]
}
If you glance over the above received Json, it's something like this items[0].authors[i]
here authors[i] is very dynamic, as different books have different number of authors.
How can I convert this payload to XML and then send as an XML to client
<items>
<titie></title>
<authors>
<author></author>
<author></author>
<author></author>
.
.
.
</authors>
</items>
When converting from JSON to XML I almost always use this way.
First set messageType to xml, you may also set ContentType but I am not 100% sure if it is required
<property name="messageType" scope="axis2" value="application/xml"/>
<property name="ContentType" scope="axis2" value="application/xml"/>
Next use the payload factory with an enclosing root element, set the media type to XML
<payloadFactory media-type="xml">
<format>
<SomeRequest xmlns="yourXMLNamespace">
$1
</SomeRequest>
</format>
<args>
<arg evaluator="json" expression="."/>
</args>
</payloadFactory>
Now you will have something that looks like this.
<SomeRequest>
<items>
<volumeInfo></volumeInfo>
<title>Web Services</title>
<authors>Gustavo Alonso</authors>
<authors>Fabio Casati</authors>
<authors>Harumi Kuno</authors>
<authors>Vijay Machiraju</authors>
<publisher>Springer Science & Business Media</publisher>
<publishedDate>2003-09-04</publishedDate>
</items>
<items>
...
</items>
</SomeRequest>
See how it unwrapped the JSON array, it created multiple elements all using the array name. To get from here to the response format you want the easiest way to do it is using an xslt transform.
<xslt key="{name of your xslt transform file}"/>
Then you can respond to back to the client.
It may be worthwile checking out the JSON Support page in the wso2 docs. It covers how JSON is converted to and from XML
https://docs.wso2.com/display/EI620/JSON+Support
In the outsequence you can use a payload mediator to construct the xml from JSON.
https://docs.wso2.com/display/ESB500/PayloadFactory+Mediator

XPath/JSONPath search of arrays

Our REST API is returning an array of nested objects. Using XPath or JSONPath, I would like to extract the id elements of each top level array object but not the children's id elements.
[
{
"id":"1",
"child":{
"id":"a"
}
},
{
"id":"2",
"child":{
"id":"b"
}
}
]
The expected output is 1, 2 and NOT 1, a, 2, b.
Can anybody help with the query syntax? I have the example at http://jsfiddle.net/dqvrfvc1/2/
Try selecting the id at a specific level:
search = JSON.search(data, '/*/*/id')
See the update here: http://jsfiddle.net/dqvrfvc1/5/
If we dump the XML to the console (console.log(JSON.toXML(data));) we see:
<d:data xmlns:d="defiant-namespace" d:constr="Array" d:mi="9">
<d:item d:mi="4">
<id d:constr="String" d:mi="1">1</id>
<child d:mi="3">
<id d:constr="String" d:mi="2">a</id>
</child>
</d:item>
<d:item d:mi="8">
<id d:constr="String" d:mi="5">2</id>
<child d:mi="7">
<id d:constr="String" d:mi="6">b</id>
</child>
</d:item>
</d:data>
This means that instead of /*/*/id, we can be even more specific with:
search = JSON.search(data, '/d:data/d:item/id')
Note: Namespace selection isn't possible, so there doesn't seem to be the need to bind the d: namespace prefix to the defiant-namespace uri.
Also, take a look at the "XPATH EVALUATOR" section of http://defiantjs.com and switch between XML and JSON views to see how the JSON is represented in XML. This will help you understand the the data structure and at what level id would be found.
Given you have jmeter in your tags here is a solution for it:
JSON Path Expression should look like: $[*].id
Demo:
References:
JSON Extractor
JSON Path: Getting Started
API Testing With JMeter and the JSON Extractor
You mentioned XPath: in XPath 3.1 this is
parse-json($data)?*?id

how to form payload for the following JSON in wso2 esb

Following is the JSON trying add in payload factory mediator(wso2 esb 4.8.1):
{
"root":"<abc>
<ab>
<id>361</id>
<name>What’s your number</name>
<age>number</age>
</ab>
</abc>"
}
When i add this in payload factory mediator succesfully added but when re-open again xml tags are not there only JSON payload is there like below:
{"root":""}
I need to know how to add these kind of payloads in WSO2 ESB as a payload/request for any one of the servcie.
The problem is that you have xml structure inside json. Try this payloadFactory:
<payloadFactory media-type="json">
<format>
{"root":
{"abc":
{"ab":
{"id":"362","name":"What’s your number","age":"number"}
}
}
}
</format>
<args/>
</payloadFactory>
You can find more information here: https://docs.wso2.com/display/ESB481/JSON+Support

Apigee; Rest > Soap (using POST), json payload parameters are not propagated

I need to use a Soap API and expose it as REST.
Something just like the Weather API discussed in this Apigee tutorial/doc
http://docs.apigee.com/tutorials/proxy-soap-service
However, in my case, instead of using a rest GET, I have to use a rest POST with the parameters in a json payload.
So instead of doing this
GET http://myapi.apigee.net/weatherrest/cityweatherbyzip?ZIP=07030
I need to do this:
POST http://myapi.apigee.net/weatherrest/cityweatherbyzip
{
"ZIP":07030
}
with apigee taking the parameter from the posted json payload and making the normal SOAP call with it.
At the moment, it doesn't seem to work, the call reaches the target but without the parameter. It returns:
{
"GetCityWeatherByZIPResponse":{
"GetCityWeatherByZIPResult":{
"Success":"false",
"ResponseText":"Invalid ZIP",
"State":{
},
"City":{
},
"WeatherStationCity":{
},
"WeatherID":-1,
"Description":{
},
"Temperature":{
},
"RelativeHumidity":{
},
"Wind":{
},
"Pressure":{
},
"Visibility":{
},
"WindChill":{
},
"Remarks":{
}
}
}
}
What should i do to make sure parameters are taken from my json payload and propagated to the SOAP target call? Many Thanks
Actually, this is all related to those ExtractVariable block.
See this:
http://docs.apigee.com/api-services/reference/extract-variables-policy
So in this case, something like this should be used:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="true" enabled="true" name="GetCityWeatherByZIP-extract-form-param">
<DisplayName>GetCityWeatherByZIP Extract Form Param</DisplayName>
<Source clearPayload="true|false">request</Source>
<JSONPayload>
<Variable name="ZIP" type="string">
<JSONPath>$.ZIP</JSONPath>
</Variable>
</JSONPayload>
<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</ExtractVariables>
in Api > Develop > policy
(the one corresponding to the first step of your PUT)