I have done coding in dataweava as
%dw 1.0
%input payload application/xml
%output application/xml skipNullOn="everywhere"
---
{((payload.*Order default []) map {
Order:{
Channel:$.#EnterpriseCode,
Code:$.#OrderNo,
Status:$.#Status,
OrderLines: {
(($.OrderLines.*OrderLine default []) map {
OrderLine:{
EntryNumber:"abc",
Status:$.#Status,
(($.OrderStatuses.*OrderStatus default []) map {
ShipDate:$.#StatusDate
})
}})}
}
}
)
}
But its giving error when assigning input as
<?xml version="1.0" encoding="UTF-8"?>
<Order EnterpriseCode="111" OrderNo="222" Status="Scheduled">
<OrderLines>
<OrderLine PrimeLineNo="2" Status="Shipped" OrderedQty="1000">
</OrderLine>
</OrderLines>
</Order>
Any suggestions here? I have tried default [] but its not working. When assigning null node its giving error. I have tried filter as filter ($ != '')
XML input example:
<?xml version="1.0" encoding="UTF-8"?>
<Order EnterpriseCode="111" OrderNo="222" Status="Scheduled">
<OrderLines>
<OrderLine PrimeLineNo="2" Status="Shipped" OrderedQty="1000">
<OrderStatuses>
<OrderStatus StatusDate="statusDate"></OrderStatus>
<OrderStatus StatusDate="statusDate"></OrderStatus>
</OrderStatuses>
</OrderLine>
<OrderLine PrimeLineNo="3" Status="Shipped3" OrderedQty="10003" ></OrderLine>
</OrderLines>
</Order>
Note: In your example there are spaces between OrderLine open tag and close tag, you have to fix it:
<OrderLine PrimeLineNo="3" Status="Shipped3" OrderedQty="10003" ></OrderLine>
Dataweave script:
%input payload application/xml
%output application/xml skipNullOn="everywhere"
---
{
((payload.*Order default []) map {
Order:{
Channel:$.#EnterpriseCode,
Code:$.#OrderNo,
Status:$.#Status,
OrderLines: {
(($.OrderLines.*OrderLine default []) map {
OrderLine:{
EntryNumber:"abc",
Status:$.#Status,
(($.OrderStatuses.*OrderStatus default []) map ((key,pos) -> {
ShipDate:key.#StatusDate
}) when $!='' otherwise {})
}
})
}
}
})
}
You can't map a value if it doesn't exist, so you have to use "when/otherwise" to verify the existence of the elements.
Try this:
This should solve your issue. (Unless not/otherwise) or (when/otherwise), any combination can be used as per your requirement. "Unless not" is recommended if ShipDate is present in most cases, else replace "unless not" with "when".
%dw 1.0
%input payload application/xml
%output application/xml skipNullOn="everywhere"
---
{
(
(payload.*Order default []) map {
Order: {
Channel:$.#EnterpriseCode,
Code:$.#OrderNo,
Status:$.#Status,
OrderLines: {
(
($.OrderLines.*OrderLine default []) map ({
OrderLine: {
EntryNumber:"abc",
Status:$.#Status,
(
($.OrderStatuses.*OrderStatus) map {
ShipDate:$.#StatusDate
}
)
}
}) unless not $.OrderLines.*OrderLine.OrderStatuses? otherwise {
OrderLine: {
EntryNumber:"abc",
Status:$.#Status
}
}
)
}
}
}
)
}
Try following approaches:
use "SkipNullOn" %output application/xml skipNullOn="everywhere"
You can use when condition as shown below yourField: "null" when
payload.yourField == null otherwise payload.yourField
Giving below the structure definition of Mule Message Object has
Message
Inbound Property
Outbound Property
Payload
Variable
Flow Variable
Session Variable
Attachment
Exception Payload
When a connector of a flow (listening on a port) receives the payload its called Inbound endpoint.
When in a flow we have a connectore placed in the middle and send a payload its called Oubound endpoint. Here the all the outbound properties sent to the Http Outbound flow become Inbound Properties within that flow.
For detailed explanation see the link below.
https://docs.mulesoft.com/mule-user-guide/v/3.8/mule-message-structure.
Related
I have a JSON input:
{
abc: "",
def: "hello"
}
I want to make this blank element as nillable in XML i.e. . I am using the below dataweave code:
%dw 2,0
output application/xml skipNullOn="everywhere"
var makeNil= (in) ->
in match {
case is Array -> in map makeNil($)
case is Object -> in mapObject (
if ( ($) == "")
($$) #(xsi#'nil':true): {}
else ($$): makeNil($)
)
else -> in
}
---
makeNil(payload)
I am not able to create an attribute using #(xsi#'nil':true) for key($$). Please help me
Solving the errors that I mentioned in my comment, adding a root element works. Remember that XML unlike JSON requires a root element.
%dw 2.0
output application/xml skipNullOn="everywhere"
ns xsi http://www.w3.org/2001/XMLSchema-instance
var makeNil= (in) ->
in match {
case is Array -> in map makeNil($)
case is Object -> in mapObject (
if ( ($) == "")
($$) #(xsi#'nil':true): {}
else ($$): makeNil($)
)
else -> in
}
---
top: makeNil(payload)
input:
{
"abc": "",
"def": "hello"
}
output:
<?xml version='1.0' encoding='UTF-8'?>
<top>
<abc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<def>hello</def>
</top>
Is it possible to access data with wildcard in dataweave?
I have my payload as Entry_1_m1,Entry_2_m1,Entry_3_m1
Entries will be dynamic there might be other entry as Entry_1_m2,Entry_2_m2,Entry_3_m2.
So I should be able to get the values irrespective of last number that is I should get the value of (Entry_1_m*). Is it possible in dataweave?
%dw 1.0
%input payload application/java
%output application/xml
---
{
Employee:{
empRequest:{
ReqNumber:payload.RequestNumber,
Reasons:{
Entry:payload.Entry_1_m1,
Entry:payload.Entry_2_m1,
Entry:payload.Entry_3_m1
}
}
}
}
Use pluck operator to get list of keys which will help you to map all fields starting with Entry_1_m. Following code worked for me
%dw 1.0
%input payload application/java
%output application/xml
%var keys = (payload pluck $$) filter ($ startsWith 'Entry_1_m')
---
{
Employee:{
empRequest:{
ReqNumber:payload.RequestNumber,
Reasons: {(keys map {
Entry:payload[$]
})}
}
}
}
Hope this helps.
I have input data as list of maps like [{id="200" name="aaa"},{id="100",name="shbd"}].
I want to transform it to JSON like below
{
[
{
id="200",
name="aaa"
},
{
id="100",
name="shbd"
}
]
}
If the fields(keys in map) do no change, then it is simple and straightforward. Now how to transform if I dont know the key values. For eg, what if after sometime the input of map is [{"age":90},{"age","45"}]
It's always better to do specific mapping but you can go with the following , it will transform it into JSON
%dw 1.0
%output application/json
---
payload
As Anirban said, please validate the json you want to transform.
You can use below transformation for o/p specified below:
Transformation
---------------
%dw 1.0
%output application/json
---
payload map {
"id" : $.id,
"name" : $.name
}
---------------
expected output
--------------
[
{
id="200",
name="aaa"
},
{
id="100",
name="shbd"
}
]
If I have xml like so....
<Root>
<Authority>Water</Authority>
<Sanctions>
<Sanction>
<SanctionCode>11</SanctionCode>
<SanctionDesc>First Sanction</SanctionDesc>
</Sanction>
<Sanction>
<SanctionCode>11</SanctionCode>
<SanctionDesc>Second Sanction</SanctionDesc>
</Sanction>
</Sanctions>
</Root>
Using DataWeave how can I create a json array of Santions using only the SanctionDesc?
I've tried this but it's not right...
%dw 1.0
%output application/json
---
records: payload.Root map {
Authority: $.Authority,
sanctions: $.Sanctions.Sanction map [$.SanctionDesc]
}
I want my output to look like this...
{
"records": [{
"Authority": "Water",
"sanctions": ["First Sanction", "Second Sanction"]
}]
}
Try this
%dw 1.0
%output application/json
---
records: {
Authority: payload.Root.Authority,
sanctions: payload.Root.Sanctions..SanctionDesc
}
Or
%dw 1.0
%output application/json
---
records: {
Authority: payload.Root.Authority,
sanctions: payload.Root.Sanctions.*Sanction map $.SanctionDesc
}
Hope this helps.
Understading the map operator is the key when picking and choosing elements from input payload. Map operator goes through all the array elements on the left hand side and we can pick the values from on right hand side, Giving example from Mulesoft portal
%dw 1.0
%output application/json
users: ["john", "peter", "matt"] map ((firstName, position) -> position ++ ":" ++ upper firstName)
Output:
{
"users": [
"0:JOHN",
"1:PETER",
"2:MATT"
]
}
See link below:
https://docs.mulesoft.com/mule-user-guide/v/3.8/dataweave-operators#map
I am using dataweave, due to sales taxes in each state, I need to assign a each customer from a specific state to a pre-defined user.
However when I create this in dataweave I end up with this as my XML:
<Customer>
<Number>
<Number>
<Number>
<Number>WEB002</Number>
</Number>
</Number>
</Number>
I just need one 'number' node underneath the 'customer' node.
Here is my dataweave:
Customer:{
Number: 'WEB001' when payload.order.billing_address.state == 'Indiana' otherwise
Number: 'WEB002' when payload.order.billing_address.state == 'Kentucky' otherwise
Number: 'WEB003' when payload.order.billing_address.state == 'Illinois' otherwise
Number: 'WEB004'
},
Have tried placing my conditions inside of brackets, no joy, have tried to wrap each condition in brackets, no joy.
Is there a better way to do this?
A very easy and simple way to do that as follows:-
<dw:transform-message doc:name="Transform Message">
<dw:input-payload doc:sample="empty.xml" />
<dw:set-payload><![CDATA[%dw 1.0
%output application/xml
---
{
Customer:
Number: "WEB001" when payload.order.billing_address.state == "Indiana"
otherwise (
"WEB002" when payload.order.billing_address.state == "Kentucky"
otherwise (
"WEB003" when payload.order.billing_address.state == "Illinois"
otherwise "WEB004"))
}
]]></dw:set-payload>
</dw:transform-message>
you can put the mapping between state and number in a map/dictionary which would improve the readability like this:
%var numbers = {
Indiana: 'WEB001',
Kentucky: 'WEB002',
Illinois: 'WEB003'
}
this is what your dataweave would look like:
%dw 1.0
%output application/xml
%var defaultNumber = 'WEB004'
%var numbers = {
Indiana: 'WEB001',
Kentucky: 'WEB002',
Illinois: 'WEB003'
}
---
Customer: {
Number: numbers[payload.order.billing_address.state]
default defaultNumber
}
and here is a screenshot containing sample data and the resulting preview: