The two jsons i need to concatenate to convert it into a single valid json are :
{
"first": true,
"second": {
"name": "manoj",
"age": "45"
},
"third": {
"fourth": [{
"class": "test12",
"salary": "123456"
},
{
"class": "test23",
"salary": "15678"
}
],
"fifth": "hello"
}
}
and
[{
"item1": "123456",
"item2": "5678"
},
{
"item1": "8976",
"item2": "abcd"
}]
Is it possible to concatenate these two without using any jquery. I need something related to wso2 esb code. I tried using enrich and other mediators but no luck so far.
You can concat the jsons using WSO2 ESB Payload Factory mediator as follows,
<api xmlns="http://ws.apache.org/ns/synapse" name="ConcatAPI" context="/concat">
<resource methods="GET">
<inSequence>
<call>
<endpoint>
<http method="GET" uri-template="http://www.mocky.io/v2/56b2d88c13000057518945d4"/>
</endpoint>
</call>
<enrich>
<source type="body" clone="true"/>
<target type="property" property="first-json"/>
</enrich>
<log level="custom">
<property name="First json" expression="get-property('first-json')"/>
</log>
<call>
<endpoint>
<http method="GET" uri-template="http://www.mocky.io/v2/56b2d87d1300007c518945d3"/>
</endpoint>
</call>
<payloadFactory media-type="xml">
<format>
<completeJson xmlns="">
<firstjson>$1</firstjson>
<secondjson>$2</secondjson>
</completeJson>
</format>
<args>
<arg evaluator="xml" expression="get-property('first-json')"/>
<arg evaluator="xml" expression="$body"/>
</args>
</payloadFactory>
<property name="messageType" value="application/json" scope="axis2"/>
<send/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
Note that i have retrieved your jsons from mocked services from mocky.io web site.
Thanks.
Related
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!
I have two json from two different endpoints, i need to concatenate to convert it into a single valid json. I did it, but the first WSO2 json returns it as a string (firstjson). I would like it to be all a json.
FIRST JSON
{
"first": true,
"second": {
"name": "manoj",
"age": "45"
},
"third": {
"fourth": [
{
"class": "test12",
"salary": "123456"
},
{
"class": "test23",
"salary": "15678"
}
],
"fifth": "hello"
}
}
SECOND JSON
[
{
"item1": "123456",
"item2": "5678"
},
{
"item1": "8976",
"item2": "abcd"
}
]
XML API
<api context="/concat" name="concat" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET" url-mapping="/concatenare">
<inSequence>
<call>
<endpoint>
<http method="get" uri-template="http://www.mocky.io/v2/56b2d88c13000057518945d4">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
<enrich>
<source clone="false" type="body"/>
<target property="first-json" type="property"/>
</enrich>
<log level="custom">
<property expression="get-property('first-json')" name="First json"/>
</log>
<call>
<endpoint>
<http method="get" uri-template="http://www.mocky.io/v2/56b2d87d1300007c518945d3">
<suspendOnFailure>
<initialDuration>-1</initialDuration>
<progressionFactor>1</progressionFactor>
</suspendOnFailure>
<markForSuspension>
<retriesBeforeSuspension>0</retriesBeforeSuspension>
</markForSuspension>
</http>
</endpoint>
</call>
<log level="custom">
<property expression="get-property('first-json')" name="*********BEFOREEEEEEEE"/>
</log>
<!-- <enrich>
<source clone="false" property="first-json" type="property"/>
<target type="body"/>
</enrich> -->
<payloadFactory media-type="xml">
<format>
<completeJson xmlns="">
<firstjson>$1</firstjson>
<secondjson>$2</secondjson>
</completeJson>
</format>
<args>
<arg evaluator="xml" expression="get-property('first-json')"/>
<arg evaluator="xml" expression="$body"/>
</args>
</payloadFactory>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<send/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
RESPONSE API
{
"completeJson": {
"firstjson": "{\"first\":true,\"second\":{\"name\":\"manoj\",\"age\":\"45\"},\"third\":{\"fourth\":[{\"class\":\"test12\",\"salary\":\"123456\"},{\"class\":\"test23\",\"salary\":\"15678\"}],\"fifth\":\"hello\"}}",
"secondjson": {
"Body": [
{
"item1": 123456,
"item2": 5678
},
{
"item1": 8976,
"item2": "abcd"
}
]
}
}
}
Where am I wrong ?
Thanks in advance guys
Ok guys,
I solved it, I was wrong with the payloadFactory, the format it had to be of type json.
<payloadFactory media-type="json">
<format>
{
"completeJson" : {
"firstjson" : $1,
"secondjson" : $2
}}
</format>
<args>
<arg expression="get-property('first-json')" />
<arg expression="$body" />
</args>
</payloadFactory>
thanks anyway guys :)
Do we have some idea how Transforming json with array for new json with another fields.
I have example json. This sample json is dynamic. Can have three or four elements in array.
"insurer": [
{
"data": {
"first_name": "Name",
"last_name": "SureName"
}
},
{
"data": {
"first_name": "Name1",
"last_name": "SureName1"
}
}],
And I'd like receive json
"insurer": [
{
"data": {
"name": "Name",
"nameLast": "SureName"
}
},
{
"data": {
"name": "Name1",
"nameLast": "SureName1"
}
}],
I did this sequence
<foreach id="foreach_1" expression="//insurer/data">
<sequence>
<payloadFactory media-type="json">
<format>{ "name" : "$1",
"nameLast" : "$2" }
</format>
<args>
<arg evaluator="xml" expression="//first_name"/>
<arg evaluator="xml" expression="//last_name"/>
</args>
</payloadFactory>
<log>
<property name="message" value="petla"/>
</log>
</sequence>
</foreach>
Unfortunately, I'm only getting a partial json. You may have an idea
{ ,"name" : "Name1", "nameLast" : "SureName1" }
I'm using WSO2 ESB V6.1.0
With 3 changes to your sequence, this should work as expected.
First change the expression of the foreach modiator to //insurer,
since your JSON message has array for insurer.
Next, use XML as the
media-type of the payload factory mediator and compose a single
expected insurer element.
Finally set messageType property to change the message type to JSON.
Find sample code below.
<foreach xmlns:ns="http://org.apache.synapse/xsd"
expression="//insurer">
<sequence>
<payloadFactory media-type="xml">
<format>
<insurer>
<data>
<name>$1</name>
<nameLast>$2</nameLast>
</data>
</insurer>
</format>
<args>
<arg evaluator="xml" expression="//first_name"/>
<arg evaluator="xml" expression="//last_name"/>
</args>
</payloadFactory>
</sequence>
</foreach>
<property name="messageType" value="application/json" scope="axis2"
type="STRING"/>
The response format like this in WSO2 ESB:
<testresponse xmlns="http://abcd/service">
<cookie>yummy</cookie>
<product>YM11</product>
<place>US</place>
</testresponse >
But I just want the body, how can I do?
<cookie>yummy</cookie>
<product>YM11</product>
<place>US</place>
The goal is to transform the xml in a JSON object like the following
{
"cookie": "yummy",
"product": "YM11",
"place": "US"
}
You can use the payloadFactory
<payloadFactory media-type="xml">
<format>
<jsonObject>
<cookie>$1</cookie>
<product>$2</product>
<place>$3</place>
</jsonObject>
</format>
<args>
<arg evaluator="xml" expression="//cookie"/>
<arg evaluator="xml" expression="//product"/>
<arg evaluator="xml" expression="//place"/>
</args>
</payloadFactory>
But as already commented you need an enclosing element if not your xml will simply not be valid. If the goal is to output Json this element should be called jsonObject (find more info here : https://docs.wso2.com/display/EI600/JSON+Support).
If you don't need XML the best approach would be to directly build your json object
<payloadFactory media-type="json">
<format>
{
"cookie": $1,
"product": $2,
"place": $3
}
</format>
<args>
<arg evaluator="xml" expression="//cookie"/>
<arg evaluator="xml" expression="//product"/>
<arg evaluator="xml" expression="//place"/>
</args>
</payloadFactory>
I have defined a api in wso2 esb and it calls two internal APIs through recepient list and which are passing json responses as follows.(sample responses)
{
"name": "api1",
"response": "success",
"status": "1"
}
and
{
"name": "api2",
"response": "unsuccess",
"status": "2"
}
I need to pass the response by aggregating both of these responses as a single response. I red about payloadfactory and able to construct aggregated response. But i need to aggregate whatever the responses coming from these 2 apis and generate response as one single json object and pass by including both of these responses as follows
{
"response1": {
"name": "api1",
"response": "success",
"status": "1"
},
"response2": {
"name": "api2",
"response": "unsuccess",
"status": "2"
}
}
so how can a accomplish with WSO2ESB. I'm using latest version of ESB.
I have created three APIs and aggregated the API responses using Clone ,Below is my API which is used for aggregating responses of two API endpoints
<api xmlns="http://ws.apache.org/ns/synapse" name="aggregateResponse" context="/aggregate">
<resource methods="POST">
<inSequence>
<clone id="aggr">
<target>
<sequence>
<call>
<endpoint>
<http method="GET" uri-template="http://localhost:8280/getresponse1"/>
</endpoint>
</call>
<log>
<property name="Logger1" expression="json-eval($.)"/>
</log>
</sequence>
</target>
<target>
<sequence>
<call>
<endpoint>
<http method="GET" uri-template="http://localhost:8280/getResponse2"/>
</endpoint>
</call>
<log>
<property name="Logger1" expression="json-eval($.)"/>
</log>
</sequence>
</target>
</clone>
<payloadFactory media-type="json">
<format>{"responses":{ "name":"$1","response":"$2","status":"$3"}}</format>
<args>
<arg evaluator="json" expression="$.name"/>
<arg evaluator="json" expression="$.response"/>
<arg evaluator="json" expression="$.status"/>
</args>
</payloadFactory>
<loopback/>
</inSequence>
<outSequence>
<property name="res" scope="default">
<ResponseDetail xmlns=""/>
</property>
<aggregate id="aggr">
<completeCondition>
<messageCount min="-1" max="-1"/>
</completeCondition>
<onComplete expression="$body//responses" enclosingElementProperty="res">
<payloadFactory media-type="json">
<format>{"response1":$1 ,"response2":$2}</format>
<args>
<arg evaluator="json" expression="$.ResponseDetail.responses[0]"/>
<arg evaluator="json" expression="$.ResponseDetail.responses[1]"/>
</args>
</payloadFactory>
<send/>
</onComplete>
</aggregate>
</outSequence>
</resource>
</api>
API 1:
<api xmlns="http://ws.apache.org/ns/synapse" name="response1" context="/getresponse1">
<resource methods="GET">
<inSequence>
<payloadFactory media-type="json">
<format>{ "name": "api1", "response": "success", "status": "1"}</format>
<args/>
</payloadFactory>
<respond/>
</inSequence>
</resource>
</api>
API 2:
<api xmlns="http://ws.apache.org/ns/synapse" name="response2" context="/getResponse2">
<resource methods="GET">
<inSequence>
<payloadFactory media-type="json">
<format>{ "name": "api2", "response": "unsuccess", "status": "2"}</format>
<args/>
</payloadFactory>
<respond/>
</inSequence>
</resource>
</api>
Well, this is where enrich mediator becomes handy. Please try this out. I have not tested this since I am not doing WSO2 related stuffs now. But your feedback is warmly welcome. The pseudo code is something like this.
<call>
<endpoint>
<http method="GET" uri-template="http://www.mocky.io/v2/some-ep"/>
</endpoint>
</call>
<enrich>
<source type="body" clone="true"/>
<target type="property" property="first-json"/>
</enrich>
<call>
<endpoint>
<http method="GET" uri-template="http://www.mocky.io/v2/another-ep"/>
</endpoint>
</call>
<enrich>
<source type="property" property="first-json" clone="true"/>
<target action="sibling" xpath="//"/>
</enrich>
</respond>