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?
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 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 have logs like the following:
{
"log": {
"header": {
"key": "value",
"nested": "{\"key1\":\"value\",\"key2\":\"value\"}",
"dateTime": "2019-05-08T20:58:06+00:00"
},
"body": {
"path": "/request/path/",
"method": "POST",
"ua": "curl/7.54.0",
"resp": 200
}
}
}
I'm trying to aggregate logs using fluentd and I want the entire record to be JSON. The specific problem is the "$.log.header.nested" field, which is a JSON string. How can I parse and replace that string with its contents?
For clarity, I'd like the logs output by fluentd to look like this:
{
"log": {
"header": {
"key": "value",
"nested": {
"key1": "value",
"key2": "value"
},
"dateTime": "2019-05-08T20:58:06+00:00"
},
"body": {
"path": "/request/path/",
"method": "POST",
"ua": "curl/7.54.0",
"resp": 200
}
}
}
I've found a way to parse the nested field as JSON, but storing to back to the same key it was parsed from isn't clear. It doesn't seem like hash_value_field supports storing to a nested key. Is there some other way to accomplish this?
The following config seems to accomplish what I want. However, I'm not sure if this is the best way. I assume using ruby is far less performant. Any improvements to this are welcome.
<filter logs>
#type parser
key_name "$.log.header.nested"
hash_value_field "parsed_nested"
reserve_data true
remove_key_name_field true
<parse>
#type json
</parse>
</filter>
<filter logs>
#type record_transformer
enable_ruby true
<record>
parsed_nested ${record["log"]["header"]["nested"] = record["parsed_nested"]}
</record>
remove_keys parsed_nested
</filter>
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.
I am confused why the extractVariables rule I am using is returning data as it is. See Below.
The json to Parse is:
{
"callNotificationSubscriptionList": {
"playAndCollectInteractionSubscription": [],
"recognitionInteractionSubscription": [],
"playAndRecordInteractionSubscription": [],
"callDirectionSubscription": [],
"callEventSubscription": [
{
"clientCorrelator": "112345",
"resourceURL": "http:someurl",
"callbackReference": {
"notifyURL": "someotherurlt",
"notificationFormat": "XML"
},
"filter": {
"data1": "data abc",
"data2": "data def",
"data3": "data xyz"
}
}
]
}
}
The rule:
<JSONPayload>
<Variable name="callNotSubL">
<!-- <JSONPath>$.callNotificationSubscriptionList</JSONPath> -->
<JSONPath>$.*</JSONPath>
</Variable>
</JSONpayload>
When I use the value that is commented out, I get no response variable data. If I set the "ignoreUnresolvedVariables" parm to "false", I am returned a failure, so it has no data. Thus, I tried "$.*" With this, I am returned:
[
{
"callbackReference": {
"notifyURL": "someotherurlt",
"notificationFormat": "XML"
},
"filter": {
"data1": "data abc",
"data2": "data def",
"data3": "data xyz"
}
}
]
could this be because the EntryNames are so long? I admit they are long, but they are well under the default values in the JSON Threat Potection Policy.
I did pump this json though a web based JSONPayload parser and $.callNotificationSubscriptionList worked fine as did $.callNotificationSubscriptionList.callEventSubscription[0] which is what I am really after. But, if I can't get the top level right, I can't get the sub-levels at all.
I solved this issue using #Santanu's comments:
It seems that the JSON to parse getting through the policy is not same as what you are expecting? Can you try to assign entire payload to a variable using the AssignVariable policy before the JSON path extraction policy, and check the value of that variable in the debug view? That would help understand what payload value is actually passing through when you are trying to apply the json path extraction policy.
the <Source> tag was "request" and this was a response extract. I removed the <Source> tag and all is well