Reputation: 154
Can dw2.0 read path from yaml property file?
for example say input is
{
"head": {
"country": "US",
"body": {
"USStates": {
"stateName": "California",
"stateCode": "CL"
}
}
}
}
I have to fetch stateCode value from above request. Based on country name, the path changes every time (like ChinaStates,IndiaStates etc)
So is there a way to pass input path as parameter to Data weave? We are using yaml properties. I tried below code, its resulting in null value
%dw 2.0
output application/json
---
if(p("countryName." ++ (payload.head.country as String)) != null)
payload.p("countryName." ++ (payload.head.country))
else "not in scope"
and in yaml it declared as below
countryName:
US : head.body.USStates.stateCode
INDIA : head.body.IndiaStates.stateCode
I even tried passing path from payload then it was taking as string. please suggest
Upvotes: 1
Views: 1814
Reputation:
Try this:
I did use a variable for the path instead of reading it from the YAML config for the sake of simplicity.
%dw 2.0
output application/json
var data = {
"head": {
"country": "US",
"body": {
"USStates": {
"stateName": "California",
"stateCode": "CL"
}
}
}
}
var path = "head.body.USStates.stateCode"
---
path splitBy /\./ reduce (e,acc=data) -> acc[e]
Edit: if you need an explanation, just ask and I 'll re-edit later on with all the details. No time right now :).
Edit1: Have a look at this answer for an explanation of reduce
.
Upvotes: 5
Reputation: 1910
Is the stateName
and stateCode
piece consistent? If so you could do something like this:
%dw 2.0
output application/json
---
{
country: payload.head.country,
stateName: payload.head.body[0].stateName,
stateCode: payload.head.body[0].stateCode
}
Output:
{
"country": "US",
"stateName": "California",
"stateCode": "CL"
}
But yes, you can address it like this:
payload.head.body[p('countryName.$(payload.head.country)')].stateCode
should also work, though more complicated than necessary.
Edit:
I see based on your answer why this wouldn't necessarily work. George's answer is correct, but I thought I'd throw this in as well since it is a slightly more complete function for doing this:
%dw 2.0
output application/json
fun getField(payload: Any, field: String) = do {
var path = field splitBy '.' reduce((pathPart, path=[]) ->
if (pathPart contains '[') do {
var pieces = pathPart splitBy '['
---
pieces reduce((piece,subPath=path) ->
if (piece contains ']') subPath << (piece replace ']' with '') as Number
else subPath << piece
)
}
else path << pathPart
)
---
getField(payload, path)
}
fun getField(payload: Any, field: Array) =
if (sizeOf(log('field',field)) == 1) payload[field[0]]
else getField(payload[field[0]], field[1 to -1])
Using this function you would do:
%dw 2.0
output application/json
---
getField(payload, p('country.$(payload.head.country)'))
This is a get field by path function.
Upvotes: 2
Reputation: 25699
It looks like the structure is too complex for the builtin selectors. I don't think you can use the DataWeave single-value selector (the dot '.') inside a dynamic expression in that way. If you leave only the attribute name in the property it will work. I recommend to simplify the data if possible.
Example:
Property countrName.US: "USStates"
and the expression:
payload.head.body[p("countrName.US")].stateCode
Otherwise if you absolutely need a path expression see George's answers.
Upvotes: 1