I am making use of XSLT mediator to form the following JSON payload:
{
"products": [
{
"product_id": 1,
"product_name" : "abc"
},
{
"product_id": 2,
"product_name" : "xyz"
}
]
}
Based on the response I get from the api using the above payload, I need to create another json payload(below) and append it to make another api call.
{
"amount": {
"total_amount": 0.46,
"total_tax": 0
}
}
I want the final payload to look like
{
"products": [
{
"product_id": 1,
"product_name" : "abc"
},
{
"product_id": 2,
"product_name" : "xyz"
}
],
"amount": {
"total_amount": 0.46,
"total_tax": 0
}
}
How can I achieve this on WSO2 Integration studio?
I think XSLT is an overkill for this and I don't think Datamapper is a viable option here, given we are dealing with multiple inputs. You can simply use the Enrich Mediator for this. Here is an example for your payloads. I tried to provide an example as close to your requirement, I have hardcoded the payloads, and the Payload Factory depicts your backend call response and the original PL.
<?xml version="1.0" encoding="UTF-8"?>
<api context="/json" name="TestAPI" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET">
<inSequence>
<payloadFactory description="Build JSON" media-type="json">
<format>
{
"products": [
{
"product_id": 1,
"product_name" : "abc"
},
{
"product_id": 2,
"product_name" : "xyz"
}
]
}
</format>
<args/>
</payloadFactory>
<enrich description="First save the Original PL to a property" >
<source clone="true" type="body"/>
<target property="ORIGINAL_PL" type="property"/>
</enrich>
<payloadFactory description="Build JSON second PL" media-type="json">
<format>
{
"amount": {
"total_amount": 0.46,
"total_tax": 0
}
}
</format>
<args/>
</payloadFactory>
<enrich description="Save the PL from the second request to another property">
<source clone="true" type="body"/>
<target property="SECOND_PL" type="property"/>
</enrich>
<enrich description="Restore original payload">
<source clone="false" property="ORIGINAL_PL" type="property"/>
<target type="body"/>
</enrich>
<enrich description="Now add the second PL as a Child to the original" >
<source clone="true" property="SECOND_PL" type="property"/>
<target action="child" xpath="json-eval($)"/>
</enrich>
<log level="full"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
This is the result of the above.
{
"products": [
{
"product_id": 1,
"product_name": "abc"
},
{
"product_id": 2,
"product_name": "xyz"
}
],
"amount": {
"total_amount": 0.46,
"total_tax": 0
}
}
You can use DataMapper mediator to provide input and output schema and transform the incoming payload to the way you need. Provide either JSON or XML schema that you are receiving from the 1st service as the input schema to DataMapper and provide the schema of the expected result in either JSON or XML to the DataMatter as output schema. After that, you can map both input/ output fields and at runtime, DataMapper will do the message translation for you.
For more details - https://apim.docs.wso2.com/en/latest/tutorials/integration-tutorials/transforming-message-content/
Thanks!
Related
I want to convert my XML data to JSON using data mapper. But when I have added mapper in ESB flow and provide XML input and JSON output. It says DataMapper mediator: mapping failed. Please guide me on what is wrong with XML and JSON?
My XML input as below:-
<?xml version="1.0" encoding="UTF-8"?>
<FIXMLResponse xmlns="http://www.finacle.com/fixml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Header>
<ResponseHeader>
<RequestMessageKey>
<RequestUUID>FEBA_1553756445880</RequestUUID>
<ServiceRequestId>executeFinacleScript</ServiceRequestId>
<ServiceRequestVersion>10.2</ServiceRequestVersion>
<ChannelId>COR</ChannelId>
</RequestMessageKey>
<ResponseMessageInfo>
<BankId>04</BankId>
<TimeZone>System.CurrentSystemTimeZone</TimeZone>
<MessageDateTime>2020-02-27T20:25:13.697653+05:30</MessageDateTime>
</ResponseMessageInfo>
<UBUSTransaction>
<Id />
<Status />
</UBUSTransaction>
<HostTransaction>
<Id />
<Status>SUCCESS</Status>
</HostTransaction>
<HostParentTransaction>
<Id />
<Status />
</HostParentTransaction>
</ResponseHeader>
</Header>
<Body>
<executeFinacleScriptResponse>
<ExecuteFinacleScriptOutputVO xsi:type="xsd:string" />
<executeFinacleScript_CustomData>
<STATUS>SUCCESS</STATUS>
<ERROR>
<FIBUSINESSEXCEPTION>
<ERRORDETAIL>
<ERRORCODE>ERR0008</ERRORCODE>
<ERRORDESC>Invalid NIC Passed</ERRORDESC>
<ERRORTYPE>BE</ERRORTYPE>
</ERRORDETAIL>
</FIBUSINESSEXCEPTION>
</ERROR>
</executeFinacleScript_CustomData>
</executeFinacleScriptResponse>
</Body>
</FIXMLResponse>
My JSON Output (conversion of above XML into JSON using online tool) as below:-
{
"Header": {
"ResponseHeader": {
"RequestMessageKey": {
"RequestUUID": "FEBA_1553756445880",
"ServiceRequestId": "executeFinacleScript",
"ServiceRequestVersion": "10.2",
"ChannelId": "COR"
},
"ResponseMessageInfo": {
"BankId": "04",
"TimeZone": "System.CurrentSystemTimeZone",
"MessageDateTime": "2020-02-27T20:25:13.697653+05:30"
},
"UBUSTransaction": {
"Id": null,
"Status": null
},
"HostTransaction": {
"Id": null,
"Status": "SUCCESS"
},
"HostParentTransaction": {
"Id": null,
"Status": null
}
}
},
"Body": {
"executeFinacleScriptResponse": {
"ExecuteFinacleScriptOutputVO": {
"#type": "xsd:string"
},
"executeFinacleScript_CustomData": {
"STATUS": "SUCCESS",
"ERROR": {
"FIBUSINESSEXCEPTION": {
"ERRORDETAIL": {
"ERRORCODE": "ERR0008",
"ERRORDESC": "Invalid NIC Passed",
"ERRORTYPE": "BE"
}
}
}
}
}
}
}
If you just want to do a XML to JSON transformation without customising any values, you can use messageType property to convert and get the response. Look at the sample proxy configuration below.
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="tojson"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<property name="messageType" value="application/json" scope="axis2"/>
<respond/>
</inSequence>
</target>
<description/>
</proxy>
If you send the XML payload to this proxy, it will send a JSON response.
I want to use only XML to bind a list to the data of a JSON file.
Here is my code:
XML View:
<List
headerText="Positions"
items="{/Positions}">
<ObjectListItem
title="{positions>id}">
</ObjectListItem>
</List>
index.html
var oPositionsModel = new sap.ui.model.json.JSONModel();
oPositionsModel.loadData("model/Positions.json");
sap.ui.getCore().setModel(oPositionsModel);
model/Positions.json
{
"Positions": [
{
"id": 123456,
"article": "Abcde",
"amount": 12
},
{
"id": 654321,
"article": "Edcba",
"amount": 21
}
]
}
I can't see, what's wrong. But I get "no data" all the time.
There is nothing in the console saying there is a problem here.
Your binding for the title attribute is not correct. You want to bind it directly to the id attribute of Positions, no need to specify the model:
<List
headerText="Positions"
items="{/Positions}">
<ObjectListItem
title="{id}">
</ObjectListItem>
</List>
Working demo in JSBin
The mule payload is in flowVars (infodata)
[
{
"status": "submitted",
"identity": "",
"papers": {
"code1": "12csd3cbsdj",
"code2": "skd02nd28dn",
"date": "2016-06-22",
"party": {
"due_date": "2016-06-22",
"personel": {
"email": "tt#test.com",
"value": {
"amount": "0.10",
"inflation": "HIGH"
}
}
}
}
}
]
Inside Dataweave,
(1) how to remove the square brackets?
(2) how to replace the value of amount and inflation dynamically (from flowVars)?
Question 2:You can directly use flowVars inside dataweave or if the values are in url you can dynamically set values using inboundProperties. Refer: https://docs.mulesoft.com/mule-user-guide/v/3.7/dataweave-reference-documentation
I have used set variable where you can dynamically exact it.Test Url used in this flow: http://localhost:8083/test?inflation=HIGH
<flow name="testFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP">
</http:listener>
<logger level="INFO" doc:name="Logger"/>
<set-variable variableName="dynamicValueAmount" value="#['2']" doc:name="Variable"/>
<dw:transform-message doc:name="Transform Message">
<dw:set-payload><![CDATA[%dw 1.0
%output application/json
---
[
{
"status": "submitted",
"identity": "",
"papers": {
"party": {
"due_date": "2016-06-22",
"personel": {
"email": "tt#test.com",
"value": {
"amount": flowVars.dynamicValueAmount,
"inflation": inboundProperties.'http.query.params'.inflation
}}}}}
]]]></dw:set-payload>
</dw:transform-message>
<object-to-string-transformer doc:name="Object to String"/>
<set-payload value="#[ message.payload =org.mule.util.StringUtils.replace(message.payload,"[","{");message.payload =org.mule.util.StringUtils.replace(message.payload,"]","}")]" doc:name="Set Payload"/>
<logger level="INFO" doc:name="Logger"/>
</flow>
Regarding Question one, i have externally used replace function in set Payload( Working fine - other way). I believe it can be achieve in standard way by using Dataweave itself. Let wait for the answers.
I have resolved question #1
%dw 1.0
%output application/java
---
{
data:flowVars.infodata replace /(\[|\])/ with ""
}
I'm still trying to understand how to dynamically change the content of the payload for question #2.
Looking at the sample flowVar content, it looks like an array of json object. Is that correct? If it is array then inside dataweave, you can either iterate over flowVars.infodata map {} or just get the first object data: flowVars.infodata[0].
Not sure what you really mean by dynamically changing content. #star has shown a way how you can reference any variables inside your dataweave code. May be you can add some of your code that you are looking to edit?
I have this json payload, I would want to collect all externalListingId in one shot -
{
"listings": {
"numFound": 3,
"listing": [
{
"status": "INACTIVE",
"pricePerTicket": {
"amount": 100,
"currency": "USD",
},
"paymentType": "1",
"externalListingId": "12208278",
"city": "New York"
},
{ "status": "ACTIVE",
"pricePerTicket": {
"amount": 4444,
"currency": "USD"
},
"paymentType": "1",
"externalListingId": "CID1421798897102:151681733",
"city": "Seattle"
}
]
}
}
I am using MVEL expression -
<enricher target="#[flowVars['sData']]" source="#[(externalListingId in payload.listing)]" doc:name="Message Enricher">
<json:json-to-object-transformer returnClass="java.util.HashMap" doc:name="JSON to Object"/>
</enricher>
But this is giving error !! - Message payload is of type: ReleasingInputStream.
Scenario - I would like to collect all externalListingId into flowVariable, convert to hashmap. I have another CSV file as input, would like to loop through that payload and check if this map contains the id!!
I am following this earlier post -
Extracting array from JSON in mule esb
You need to transform the message's streaming payload to an object with:
<json:json-to-object-transformer returnClass="java.lang.Object" />
before the enricher, and remove the one you have inside of it.
You also need to fix your MEL, as the listings property is missing in it:
source="#[(externalListingId in payload.listings.listing)]"
Source: http://www.mulesoft.org/documentation/display/current/Mule+Expression+Language+Tips#MuleExpressionLanguageTips-JSONProcessing
it worked with the same definition.
<flow name="test-mule-json-extractFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/json" doc:name="HTTP"/>
<enricher source="#[(externalListingId in payload.listings.listing)]" target="#[flowVars.ids]" doc:name="Message Enricher">
<json:json-to-object-transformer returnClass="java.util.HashMap" doc:name="JSON to Object"/>
</enricher>
<logger message=":::::::::::::::#[flowVars.ids]" level="INFO" doc:name="Logger"/>
</flow>
Note: the json input you mentioned is not valid due to available of an extra comma.
With cars-jpa-archetype example, I am able to perform deep insert (Car and
Driver) in XML but not JSON. With my JSON 1 or 2 at below, only Car is
inserted and Driver is null. Any one can shed light on my JSON inputs? Have no issue with JSON input if I use Olingo annotations (#EdmEntityType etc).
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:d="
http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="
http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xml:base="
http://localhost:8080/example/MyFormula.svc/">
<category term="MyFormula.Car" scheme="
http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link href="Cars(Id=553,IdL=554L)" rel="edit" title="Car" />
<link href="Cars(Id=553,IdL=554L)/DriverDetails" rel="
http://schemas.microsoft.com/ado/2007/08/dataservices/related/DriverDetails"
title="DriverDetails" type="application/atom+xml;type=entry">
<m:inline>
<entry xml:base="http://localhost:8080/example/MyFormula.svc/">
<category term="MyFormula.Driver" scheme="
http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link href="Drivers(10L)" rel="edit" title="Driver" />
<link href="Drivers(10L)/CarDetails" rel="
http://schemas.microsoft.com/ado/2007/08/dataservices/related/CarDetails"
title="CarDetails" type="application/atom+xml;type=entry" />
<content type="application/xml">
<m:properties>
<d:Birthday>2014-12-05T14:35:11.141</d:Birthday>
<d:Id>10</d:Id>
<d:Lastname>Super</d:Lastname>
<d:Name>Speeder</d:Name>
<d:Nickname>TN</d:Nickname>
</m:properties>
</content>
</entry>
</m:inline>
</link>
<content type="application/xml">
<m:properties>
<d:Id>553</d:Id>
<d:IdL>554</d:IdL>
<d:Model>M1</d:Model>
<d:ModelYear>2014</d:ModelYear>
<d:Price>20000.0</d:Price>
<d:Updated>2014-03-20T14:35:17.075</d:Updated>
</m:properties>
</content>
</entry>
// JSON 1
{
"Id":677,
"IdL":"678",
"Model":"M1",
"ModelYear":2014,
"Price":"20000.0",
"Updated":"\/Date(1395326117075)\/",
"DriverDetails":{
"Birthday":"\/Date(1417790111141)\/",
"Id":"3",
"Lastname":"Super",
"Name":"Speeder",
"Nickname":"YZ",
"CarDetails": {
"__deferred": {
"uri": "
http://localhost:8080/example/MyFormula.svc/Drivers(3)/CarDetails"
}
}
}
}
// JSON 2
{
"d": {
"__metadata": {
"type": "MyFormula.Car"
},
"Id": 601,
"IdL": "602",
"Model": "M1",
"ModelYear": 2014,
"Price": "20000.0",
"Updated": "/Date(1395244800000)/",
"DriverDetails": {
"__metadata": {
"id": "http://localhost:8080/example/MyFormula.svc/Drivers(11L)",
"uri": "http://localhost:8080/example/MyFormula.svc/Drivers(11L)",
"type": "MyFormula.Driver"
},
"Birthday": "/Date(1417795200000)/",
"Id": "11",
"Lastname": "Super",
"Name": "Speeder",
"Nickname": "Bolt",
"CarDetails": {
"__deferred": {
"uri": "
http://localhost:8080/example/MyFormula.svc/Drivers(11L)/CarDetails"
}
}
}
}
}
Sorry for cross post here as no response from the Olingo forum.
Seems like the same issue was posted on their Jira but it should have been resolved now:
https://issues.apache.org/jira/browse/OLINGO-515