How to concatenate JSON array values in WSO2 ESB? - wso2

We have json object as like below, Expected Result in: "(001),(011),(089),(120)".
Can anyone suggest how to iterate the json array and concat the values as mention ."(001),(011),(089),(120)"
Thanks in advance.
{
"Element": {
"Values": {
"AgentID": "aaaaa",
"TransactionData": [
{
"No": "001"
},
{
"No": "011"
},
{
"No": "089"
},
{
"No": "120"
}
]
}
}
}

You can do it by using iterate mediator, filter mediator and properties with operation scope. Try this solution. At the end you will have (001),(011),(089),(120) value in concat-data property. I have added the complete proxy for your reference.
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="StockQuoteProxy"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<payloadFactory media-type="json">
<format>
{
"Element": {
"Values": {
"AgentID": "aaaaa",
"TransactionData": [
{
"No": "001"
},
{
"No": "011"
},
{
"No": "089"
},
{
"No": "120"
}
]
}
}
}
</format>
<args/>
</payloadFactory>
<iterate continueParent="true"
expression="//Element/Values/TransactionData"
sequential="true">
<target>
<sequence>
<property name="data"
expression="json-eval($.TransactionData.No)"
type="STRING"/>
<filter source="boolean(get-property('operation','concat-data'))" regex="false">
<then>
<property name="concat-data"
expression="fn:concat('(',get-property('data'),')')"
scope="operation"
type="STRING"/>
</then>
<else>
<property name="concat-data"
expression="fn:concat(get-property('operation','concat-data'),',','(',get-property('data'),')')"
scope="operation"
type="STRING"/>
</else>
</filter>
</sequence>
</target>
</iterate>
<log level="custom">
<property name="con-cat-data"
expression="get-property('operation','concat-data')"/>
</log>
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
<publishWSDL uri="file:repository/samples/resources/proxy/sample_proxy_1.wsdl"/>
<description/>
</proxy>
Payload factory mediator is used only to simulate your scenario. If your client sends this JSON payload, then you don't need to have this payload factory mediator.
Filter mediator is used to omit the leading comma character. If you do not use a filter, you will get ,(001),(011),(089),(120) as a result (note the leading comma character). Of course, there can be other ways to remove leading comma character.
Refer this for more details on properties with operation scope.

For this kind of logic I sometimes favor the script mediator, as IMO it is simpler to implement things like string splicing/joining, conditional xml/json element building and so forth.

Related

If Then else Xpath wso2

I have practice to validation alphabet and numeric. i was can validating both of them. but the return was true or false. with fn:matches combine with escape characters regex. can anyone help me to correct my validation.
My Code
<?xml version="1.0" encoding="UTF-8"?>
<api context="/a" name="A" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<property expression="json-eval($.OperationValueRegex.Value)" name="Value" scope="default" type="STRING"/>
<payloadFactory media-type="xml">
<format>
<OperationValueRegex xmlns="">
<Result1>$1</Result1>
</OperationValueRegex>
</format>
<args>
<arg evaluator="xml" expression="if($ctx:Value != '') then fn:tokenize($ctx:Value, ' ')[matches(., '^\d+$')]" xmlns:fn="http://www.w3.org/2005/xpath-functions"/>
</args>
</payloadFactory>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
Expected Result : when not input was not number there was new tag xml for description error
Sample Request:
{
"OperationValueRegex" : {
"Value" : "sadasdsadasd"
}
}
Result expected
<OperationValueRegex>
<Result1>sadasdsadasd</Result1>
<Status>the input not correct</Status>
</OperationValueRegex>
Thanks
For This requirement, you can use wso2 validate mediator. You can use the below json schema to validate the payload. You need to save this in the registry(use the media type as application/json).
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"OperationValueRegex": {
"type": "object",
"properties": {
"Value": {
"type": "number"
}
},
"required": [
"Value"
]
}
},
"required": [
"OperationValueRegex"
]
}
Then you can use the above json schema to validate the payload using validate mediator and construct the expected payload.
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="test"
startOnLoad="true"
statistics="disable"
trace="disable"
transports="http,https">
<target>
<inSequence>
<property expression="json-eval($.OperationValueRegex.Value)"
name="Value"
scope="default"
type="STRING"/>
<validate cache-schema="true">
<schema key="conf:/schema/schema.json"/>
<on-fail>
<payloadFactory media-type="xml">
<format>
<OperationValueRegex xmlns="">
<Result1>$1</Result1>
<Status>the input not correct</Status>
</OperationValueRegex>
</format>
<args>
<arg evaluator="xml" expression="$ctx:Value"/>
</args>
</payloadFactory>
<respond/>
</on-fail>
</validate>
<respond/>
</inSequence>
</target>
<description/>
</proxy>

WSO2: How can I use iterate mediator for a json array and then log each element?

I have this json file:
{
"data":{
"call_location":[
{
"id": 1,
"ycoordinate":44.4176067
},
{
"id": 2,
"ycoordinate":46.6680591712414
},
{
"id": 3,
"ycoordinate":45.4176067
}
]
}
}
And I want to have each element into a property and log the property like this:
<iterate id="jsonIterator" expression="json-eval($.data.call_location)">
<target>
<sequence>
<propertyGroup>
<property expression="json-eval($.id)" name="id" scope="default" type="NUMBER"/>
<property expression="json-eval($.ycoordinate)" name="ycoordinate" scope="default" type="NUMBER"/>
</propertyGroup>
<log level="custom">
<property expression="$ctx:id" name="log_id :"/>
<property expression="$ctx:ycoordinate" name="log_ycoordinate :"/>
</log>
</sequence>
</target>
</iterate>
When I'm sending a request through postman it's only trying to send the request endlessly ("Sending request..." message)
What am I doing wrong? Thank you
*I want to use iterate mediator not foreach
Change in the propertyGroup the properties types from type="NUMBER" to type="STRING". Propably WSO2 throws error when trying to convert into the specified type, using json-eval() function.

Payload Factory exception with invalid json

If I use a payload factory to create or simply to clean the payload in case of fault, the payload factory fail with an exception.
So, in case of error, I can't manipulate the payload.
I only need to remove it for example, so the fact that is invalid for me is not influential.
Example:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/DemoError" name="DemoError" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<payloadFactory media-type="json">
<format>{
"status":"OK"
}</format>
<args/>
</payloadFactory>
<loopback/>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<payloadFactory media-type="json">
<format>{
"status":"KO"
}</format>
<args/>
</payloadFactory>
</faultSequence>
</resource>
</api>
In this example, if I made a call with an invalid json...
The ESB, it goes in the fault sequence (right) but when I try in the fault to clean the payload, the payload factory fail (org.apache.synapse.commons.SynapseCommonsException: Existing json payload is malformed), the worst thing is that failing the fault sequence it return http 202...very bad
I'm using WSO2 EI 6.5.0
I tried out your API. It is not failing actually. If I add a <respond/> mediator after Payload Factory mediator inside Fault Sequence, I can see that the Fault Sequence payload is returning correctly.
I reproduced the issue, it's a little bit more complex.
If I have a validator, it goes in seems to go in the fault sequence, as expected, but now, the fault sequence fail on payload factory, returning http 202.
Try this:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/DemoError" name="DemoError" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<validate cache-schema="true">
<schema key="gov:custom/schema.json"/>
<on-fail>
<log level="custom">
<property name="ERROR" value="VALIDATE"/>
</log>
</on-fail>
</validate>
<payloadFactory media-type="json">
<format>{
"status":"OK"
}</format>
<args/>
</payloadFactory>
<loopback/>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence>
<log level="custom">
<property name="ERROR" value="I'M IN FAULT SEQUENCE"/>
</log>
<property name="HTTP_SC" scope="axis2" type="STRING" value="500"/>
<payloadFactory media-type="json">
<format>{
"status":"KO"
}</format>
<args/>
</payloadFactory>
<respond/>
</faultSequence>
</resource>
</api>
with the following schema:
{
"$id": "https://example.com/person.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "example",
"type": "object",
"required": [ "input"],
"properties": {
"input": {
"type": "boolean",
"description": "Input"
}
}
}
and the following input:
{
"input":xxx
}
This is related to the issue reported in [1]. Until a GA release includes the fix, the WUM updated versions will contain the fix for the EI versions including wso2ei-6.6.0.
[1]. https://github.com/wso2/product-ei/issues/2757

Enrich Json with new elements not working for me .Please guide

Enrich Json with new elements not working for me .Please guide.
Input request :
{
"id" : "1",
"make" : "NAHB"
}
I created wso2 flow named eg1.xml . I am trying to enrich the incoming json request with new element "name"
processing xml: (eg1.xml)
<?xml version="1.0" encoding="UTF-8"?>
<api context="/eg1" name="eg1" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST GET" uri-template="/hi">
<inSequence>
<log level="full"/>
<log level="custom">
<property expression="//jsonObject" name="msg1"/>
</log>
<enrich description="">
<source clone="true" type="inline">
<name xmlns="">Home</name>
</source>
<target action="child" xpath="//jsonObject"/>
</enrich>
<log level="custom">
<property expression="//jsonObject" name="msg2"/>
</log>
<log level="full"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
current output :
{
"id" : "1",
"make" : "NAHB"
}
Desired output :
{
"id" : "1",
"make" : "NAHB"
"name" : "Home"
}
logger output :
Logger1 output(log level full) :
LogMediator To: /eg1/hi, MessageID: urn:uuid:2f627daf-ac9c-4492-84ea-2736670724e8, Direction: request, Payload:
{
"id": "1",
"make": "NAHB"
}
Logger2 output :
LogMediator msg1 =
<jsonObject>
<id>1</id>
<make>NAHB</make>
</jsonObject>
Logger3 output :
LogMediator msg2 =
<jsonObject>
<id>1</id>
<make>NAHB</make>
<name>Home</name>
</jsonObject>
Logger4 output(log level full) :
LogMediator To: /eg1/hi, MessageID: urn:uuid:2f627daf-ac9c-4492-84ea-2736670724e8, Direction: request, Payload:
{
"id": "1",
"make": "NAHB"
}
Postman output :
{
"id": "1",
"make": "NAHB"
}
Regards,
Aditya
You have to add the response back to body
<api xmlns="http://ws.apache.org/ns/synapse" name="eg1" context="/eg1">
<resource methods="POST GET" uri-template="/hi">
<inSequence>
<log level="full"/>
<log level="custom">
<property name="msg1" expression="//jsonObject"/>
</log>
<enrich description="">
<source type="inline" clone="true">
<name xmlns="">Home</name>
</source>
<target action="child" xpath="//jsonObject"/>
</enrich>
<log level="full">
<property name="msg2" expression="//jsonObject"/>
</log>
<enrich>
<source clone="true" xpath="//jsonObject"/>
<target type="body"/>
</enrich>
<log level="full"/>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
I have tried this API
Request
{
"id" : "1",
"make" : "NAHB"
}
Response
{
"id": 1,
"make": "NAHB",
"name": "Home"
}
you have 3 ways to do it:
Enrich mediator: as described in the other answers
Payload Factory mediator: will require adding all the parameters in the arguments unless the new element will be in a separate sub element
Script mediator:
<script language="js">
<![CDATA[
var payload = mc.getProperty('payloadProperty'); // if original json is in property. If received as payload use: mc.getPayloadJSON();
var json = JSON.parse(payload);
var newElement = mc.getProperty('newElement'); // get the value of the new element
json.newElementName = newElement; // define it (newElementName not present in the json in the original payload
mc.setPayloadJSON(json); // put the result back as payload. Optional: read it in a property as done below if needed, otherwise just call the next service
]]>
</script>
<property expression="json-eval($)" name="json" scope="default" type="STRING"/>

Transforming JSON array with WSO2 ESB using foreach mediator

I'm using WSO2 ESB V4.9.0 to create a proxy service for a designated end point which needs to return a transformed JSON array.
I've setup a proxy service with a foreach mediator and payloadfactory in the out sequence together with log statements to see what is happening.
The result is that each of the individual array elements is transformed as expected however the individual elements are not merged back to a single array at the end of the loop
as the documentation seems to imply. The result is that only the final element is returned.
Only thing I can see is that most of the examples I've seen don't just have an element with an array rathet than just an array. Anyone know if this is possible?
Original endpoint returns something like this:
[
{"id": "1",
"type": "object",
"name": "first",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "first record"},
{"id": "2",
"type": "object",
"name": "second",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "second record"},
..etc...
]
Required return from proxy service is like this:
[
{"name": "first record",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]"},
{"name": "second record",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]"},
..etc...
]
Actual return from proxy like this:
{"name": "first record",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]"}
Configuration of the proxy is here:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="newfeed_v2"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<log/>
</inSequence>
<outSequence>
<log level="full">
<property name="MESSAGE" value="FIRST"/>
</log>
<foreach id="foreach_1" expression="//jsonArray/jsonElement">
<sequence>
<payloadFactory media-type="json">
<format>{
"name" : "$1",
"bounds" : "$2"
}</format>
<args>
<arg evaluator="json" expression="$.displayName"/>
<arg evaluator="json" expression="$.bounds"/>
</args>
</payloadFactory>
<log level="full">
<property name="MESSAGE" value="ENDLOOP"/>
</log>
</sequence>
</foreach>
<log level="full">
<property name="MESSAGE" value="LAST"/>
</log>
<log/>
<send/>
</outSequence>
<endpoint>
<address uri="https://api.backend.com"/>
</endpoint>
</target>
<description/>
</proxy>
Can you try this as a workaround:
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
name="newfeed_v2"
transports="https,http"
statistics="disable"
trace="disable"
startOnLoad="true">
<target>
<inSequence>
<payloadFactory media-type="json">
<format>[
{"id": "1",
"type": "object",
"name": "first",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "first record"},
{"id": "2",
"type": "object",
"name": "second",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "second record"},
{"id": "4",
"type": "object",
"name": "tercero",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "tercer record"}
]
</format>
<args/>
</payloadFactory>
<log level="full"/>
<loopback/>
</inSequence>
<outSequence>
<log level="full">
<property name="MESSAGE" value="FIRST"/>
</log>
<property name="Person" scope="default">
<value xmlns=""/>
</property>
<foreach id="foreach_1" expression="//jsonArray/jsonElement">
<sequence>
<payloadFactory media-type="json">
<format>{
"name" : "$1",
"bounds" : "$2"
}
</format>
<args>
<arg evaluator="json" expression="$.displayName"/>
<arg evaluator="json" expression="$.bounds"/>
</args>
</payloadFactory>
<enrich>
<source clone="true" xpath="$body//jsonObject"/>
<target action="child" xpath="$ctx:Person"/>
</enrich>
<log level="full">
<property name="MESSAGE1" value="ENDLOOP"/>
</log>
</sequence>
</foreach>
<enrich>
<source clone="true" xpath="$ctx:Person"/>
<target type="body"/>
</enrich>
<log level="full">
<property name="MESSAGE" value="ENDLOOP"/>
</log>
<!--property name="messageType" value="text/xml" scope="axis2" type="STRING"/--><log level="full">
<property name="TRANSFORMED MESSAGE" value="LAST"/>
</log>
<send/>
</outSequence>
<faultSequence/>
</target>
<description/>
</proxy>
My response:
{"value":[{"name":"first record","bounds":"[[-0.256,51.531],[-0.102,51.656]]"},{"name":"second record","bounds":"[[-0.256,51.531],[-0.102,51.656]]"},{"name":"tercer record","bounds":"[[-0.256,51.531],[-0.102,51.656]]"}]}
for each mediator will add the splitted expression to the root element so i did like this,
<api context="/foreach" name="foreach" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET">
<inSequence>
<payloadFactory media-type="json">
<format>[
{"id": "1",
"type": "object",
"name": "first",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "first record"},
{"id": "2",
"type": "object",
"name": "second",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "second record"},
{"id": "4",
"type": "object",
"name": "tercero",
"bounds":"[[-0.256,51.531],[-0.102,51.656]]",
"displayName": "tercer record"}
]
</format>
<args/>
</payloadFactory>
<log level="full">
</log>
<foreach expression="//jsonArray/jsonElement">
<sequence>
<payloadFactory media-type="xml">
<format>
<result xmlns="">
<name>$1</name>
<bounds>$2</bounds>
</result>
</format>
<args>
<arg evaluator="json" expression="$.displayName"/>
<arg evaluator="json" expression="$.bounds"/>
</args>
</payloadFactory>
</sequence>
</foreach>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<log level="full"/>
<respond/>
</inSequence>
<outSequence>
<send/>
</outSequence>
<faultSequence/>
</resource>
</api>
and i got the response like this
{ "result": [{"name": "first record","bounds": [[-0.256,51.531],[-0.102,51.656]]},{"name": "second record","bounds": [[-0.256,51.531],[-0.102,51.656]]},{"name": "tercer record","bounds": [[-0.256,51.531],[-0.102,51.656]]}]}