ProstDev ProstDev
Challenges Jun 13, 2023 · 2 min read

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.

By Alex Martinez
Thumbnail: DataWeave programming challenge #7: Modify certain values from a JSON structure Read & copy the full video transcript

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 Playground

Tip

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, 2023

    I love love love that you're using the do keyword 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, 2023

    That 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 field name with value "a" becomes "A", but the field thisname with value "def" stays the same.

  • Which DataWeave function does this challenge use to walk the JSON structure?

    It uses the mapLeafValues function from the dw::util::Tree module, which lets you transform each leaf value in the structure. Both provided solutions import mapLeafValues from dw::util::Tree and 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 with path[-1].selector and compare it to the string "thisname"; if it matches you return the value unchanged, otherwise you apply the upper function to convert it to uppercase.

  • What does `path[-1].selector` do in the solution?

    As described in Clue #4, path[-1].selector retrieves 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 the thisname field 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 with path[-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. 1.DataWeave programming challenge #1: Add numbers separated by paragraphs and get the max number
  2. 2.DataWeave programming challenge #2: Rock Paper Scissors game score system
  3. 3.DataWeave programming challenge #3: Count palindrome phrases using the Strings module
  4. 4.DataWeave programming challenge #4: Solve the Tower of Hanoi mathematical puzzle
  5. 5.DataWeave programming challenge #5: Reverse a phrase's words, but keep the punctuation
  6. 6.DataWeave programming challenge #6: Using tail-recursion to get the factorial of a number
  7. 7.DataWeave programming challenge #7: Modify certain values from a JSON structure
  8. 8.DataWeave programming challenge #8: Sum all digits to get a 1-digit number
Search

Loading search…