DataWeave programming challenge #7: Modify certain values from a JSON structure
Create a DataWeave script that will update all the values to uppercase, except the ones in which the field equals thisname.
DataWeave Programming Challenges· Part 7 of 8
- 1.DataWeave programming challenge #1: Add numbers separated by paragraphs and get the max number
- 2.DataWeave programming challenge #2: Rock Paper Scissors game score system
- 3.DataWeave programming challenge #3: Count palindrome phrases using the Strings module
- 4.DataWeave programming challenge #4: Solve the Tower of Hanoi mathematical puzzle
- 5.DataWeave programming challenge #5: Reverse a phrase's words, but keep the punctuation
- 6.DataWeave programming challenge #6: Using tail-recursion to get the factorial of a number
- 7.DataWeave programming challenge #7: Modify certain values from a JSON structure
- 8.DataWeave programming challenge #8: Sum all digits to get a 1-digit number
Try to solve this challenge on your own to maximize learning. We recommend you refer to the DataWeave documentation only. Try to avoid using Google or asking others so you can learn on your own and become a DataWeave expert!
Solve on the PlaygroundTip
Instead of trying to write the whole code yourself, browse in the documentation for any function that would do the work for you 👀
Input
Consider the following JSON input payload:
{
"name": "a",
"object": {
"name": "b",
"l": [
{
"other": "c",
"list": [
]
},
{
"thisname": "def",
"list": [
{
"this": "500e",
"l": [
{
"finalname": "f"
},
{
"finalname": "ghijk"
}
]
}
]
}
]
},
"array": [
{
"thisname": "h"
},
{
"xyz": "abc123"
}
]
}
Explanation of the problem
Create a DataWeave script that will update all the values to uppercase, except the ones in which the field equals thisname.
For example, the first field name with the value “a” has to be transformed to “A”. However, the field thisname with the value of “def” should stay the same.
Expected output
In this case, the expected output would be:
{
"name": "A",
"object": {
"name": "B",
"l": [
{
"other": "C",
"list": [
]
},
{
"thisname": "def",
"list": [
{
"this": "500E",
"l": [
{
"finalname": "F"
},
{
"finalname": "GHIJK"
}
]
}
]
}
]
},
"array": [
{
"thisname": "h"
},
{
"xyz": "ABC123"
}
]
}
Clues
If you’re stuck with your solution, feel free to check out some of these clues to give you ideas on how to solve it!
Clue #1
Check out the Tree module to see if any of those functions is useful for this case.
Clue #2
Check out the mapLeafValues function.
Clue #3
Use the upper function to transform the strings to uppercase.
Clue #4
Use path[-1].selector to retrieve the name of each value’s field and compare it with a given string value.
Answer
If you haven’t solved this challenge yet, we encourage you to keep trying! It’s ok if it’s taking longer than you thought. We all have to start somewhere ✨ Check out the clues and read the docs before giving up. You got this!! 💙
There are many ways to solve this challenge, but you can find here some solutions we are providing so you can compare your result with us.
Solution #1
%dw 2.0
import mapLeafValues from dw::util::Tree
output application/json
---
payload mapLeafValues ((value, path) ->
if (path[-1].selector == "thisname") value
else upper(value)
)
Solution #2
%dw 2.0
import mapLeafValues from dw::util::Tree
output application/json
---
payload mapLeafValues
if ($$[-1].selector == "thisname") $
else upper($)
Subscribe to receive notifications as soon as new content is published ✨
Reader notes
Helpful comments preserved from the original post.
- Sudiptaa · Jun 13, 2023
Used tree:
%dw 2.0 output application/json import * from dw::util::Tree --- payload mapLeafValues ((value, path) -> if(path.selector contains 'thisname') value else upper(value) ) - Kenneth Brennan · Jun 13, 2023
I went with a recursive solution:
%dw 2.0 output application/json fun capitalizeObject(item: Object) = do{ fun matchItem(item) = item match{ case item is Object -> item mapObject ((value, key, index) -> if(key as String == 'thisname') {(key): value} else {(key): matchItem(value)}) case item is Array -> item map ((item, index) -> matchItem(item)) case item is String -> upper(item) } --- matchItem(item) } --- capitalizeObject(payload) -
Reply to Kenneth Brennan
Alex Martinez · Jun 13, 2023I love love love that you're using the
dokeyword to create a local context. This function's structure can be used for any number of modifications in a recursive way. I love it! The only downside being that if there are more than 255 fields (or recursive calls), you will reach the StackOverflow error. But if it's a small payload like this one, you're all good! Thanks for sharing :D -
Reply to Alex Martinez
Kenneth Brennan · Jun 13, 2023That pesky stack overflow, I'm not sure how to rewrite this in the same format using tail recursion and match, hard to conceptualize. Might give it another go when I get some free time. Thanks for posting these challenges, I enjoyed this one!
- Shyam Raj Prasad · Jun 13, 2023
My solution is similar to yours with extra type check of string.
%dw 2.0 output application/json import * from dw::util::Tree --- payload mapLeafValues ((value, path) -> if(!(path[-1].selector == "thisname") and value is String) upper(value) else value )
FAQs
Frequently asked questions about this post.
-
What is the goal of DataWeave programming challenge #7?
The challenge is to create a DataWeave script that updates all the values in a JSON structure to uppercase, except the ones whose field equals
thisname. For example, the fieldnamewith value "a" becomes "A", but the fieldthisnamewith value "def" stays the same. -
Which DataWeave function does this challenge use to walk the JSON structure?
It uses the
mapLeafValuesfunction from thedw::util::Treemodule, which lets you transform each leaf value in the structure. Both provided solutions importmapLeafValues from dw::util::Treeand call it on the payload. -
How do I skip the `thisname` field while uppercasing everything else?
Inside
mapLeafValues, you check the field name of each value withpath[-1].selectorand compare it to the string"thisname"; if it matches you return the value unchanged, otherwise you apply theupperfunction to convert it to uppercase. -
What does `path[-1].selector` do in the solution?
As described in Clue #4,
path[-1].selectorretrieves the name of each value's field so you can compare it with a given string value, which is how the script decides whether a value belongs to thethisnamefield and should be left alone. -
What's the difference between the two provided solutions?
Solution #1 uses the explicit lambda form
mapLeafValues ((value, path) -> ...)and references the field name withpath[-1].selector, while Solution #2 uses the shorthand anonymous-parameter form, referencing the value with$and the field name with$$[-1].selector; both produce the same result.
More from this series
DataWeave Programming Challenges· Part 7 of 8
- 1.DataWeave programming challenge #1: Add numbers separated by paragraphs and get the max number
- 2.DataWeave programming challenge #2: Rock Paper Scissors game score system
- 3.DataWeave programming challenge #3: Count palindrome phrases using the Strings module
- 4.DataWeave programming challenge #4: Solve the Tower of Hanoi mathematical puzzle
- 5.DataWeave programming challenge #5: Reverse a phrase's words, but keep the punctuation
- 6.DataWeave programming challenge #6: Using tail-recursion to get the factorial of a number
- 7.DataWeave programming challenge #7: Modify certain values from a JSON structure
- 8.DataWeave programming challenge #8: Sum all digits to get a 1-digit number
