Search

Dark theme | Light theme
Showing posts with label DataWeaveDelight:Objects. Show all posts
Showing posts with label DataWeaveDelight:Objects. Show all posts

September 27, 2022

DataWeave Delight: Using the update Operator to change values in an object

DataWeave has some very nice features to transform data objects. One of those nice features is the update operator. With the update operator we can change values of keys in an object using a very concise syntax. We don't have to go through all keys and create a new object, but we can pinpoint the exact key and change the value. To get the correct key we use selectors. Once we have the key we can set a new value. We can define a variable to contain the current value if we want to use it to define a new value. Also is it possible to add a condition that needs to be true to change the value. Finally the update operator supports upserting a value if the key might not exist yet.

The complete syntax of the update operator is as follows:

<object> update {
    case <optional variable> at <key selector> <optional condition if (...)> -> <new value> 
}

In the following example we see several use cases of the update operator:

Source

%dw 2.0

var obj = {
    user: {
        firstName: "Hubert",
        lastName: "Klein Ikkink"
    },
    alias: "mrhaki",
    country: "NL"
}

output application/json
---
obj update {    
    // Simply use . selector to get key and set new value
    case .alias ->  "haki"
    
    // Using ! to upsert a key if doesn't exist yet.
    case .likes! -> ["Clojure", "DataWeave", "Groovy"]

    // We can use a variable for the selector value
    // and use it for a new value
    case firstName at .user.firstName -> firstName[0] ++ ".A."

    // DataWeave always provides $ as variable if we don't use at.
    // Here we can use $ to define a new value.
    case .user.lastName -> $ splitBy " " map ((item) -> item[0]) joinBy ""

    // We can add a condition for which we want to update the key
    // with a new value. In this example if country is "NL"
    // the value is "Netherlands", for other values of country
    // no transformation happens.
    case country at .country if (country == "NL") ->  "Netherlands" 
}    

Output

{
    "user": {
        "firstName": "H.A.",
        "lastName": "KI"
    },
    "alias": "haki",
    "country": "Netherlands",
    "likes": [
        "Clojure",
        "DataWeave",
        "Groovy"
    ]
    }    

Written with DataWeave 2.4.

February 23, 2022

DataWeave Delight: Reversing order of keys in objects

An object in DataWeave consists of key and value pairs. If we want to create a new object sorted by key or value we can use the orderBy function from the dw::Core module. The orderBy function takes as first argument the object. The second argument is a criteria function that can the value and key to determine how to order the object. But if we want to reverse the ordering of the key and value pairs we cannot simply use the orderBy function, because we don't have access to the index value of the key/value pair in the criteria function. We would love to have that index value, so we could negate the index value to reverse the ordering. What we need to do is first turn our object in an array of objects using the pluck function, where each object has our key and value. We can now use the orderBy function on that array of objects to reverse the order. Finally we need to reduce the array of objects into a new object using the reduce function, where the ordering of keys will be reversed.

In the following example we use :

Source

%dw 2.0

var object = {
    name: "Hubert Klein Ikkink",
    alias: "mrhaki",
    city: "Tilburg"
}

output application/json
---
{
    reverseKeys: object 
        // Turn into array: [{name: "Hubert Klein Ikkink"}, ...]
        pluck ((value, key, index) -> {(key): value})

        // Reverse the ordering based on negated index value
        orderBy ((item, index) -> -index) 

        // Transform array back to an object.
        reduce ((item, accumulator = {}) -> accumulator ++ item)
}

Output

{
  "reverseKeys": {
    "city": "Tilburg",
    "alias": "mrhaki",
    "name": "Hubert Klein Ikkink"
  }
}

Written with DataWeave 2.4.

February 8, 2022

DataWeave Delight: Using pluck function to transform object to array

Sometimes we get a data structure with keys and values and we want to create an array with data from the data structure. DataWeave gives us the pluck function to achieve this. The input argument is an object and a lambda and the output must be an array. We use a lambda to define the mapping from our object to elements in the resulting array. The lambda has three arguments: the value for a key, the key itself and the index of the key in the object. We have a handle on all data to pluck the information and transform it to elements in an array.

In the following examples we have object structure with keys book1 and book2 that we want to transform to an array. We use the infix notation of the function so our input object is followed by the pluck function and lambda:

Source

%dw 2.0

// Object structure has already an array like structure,
// but uses keys (book1, book2) for each book object.
// Using pluck we can turn this object into an array.
var books = {
    book1: {
        title: "Lord of the rings",
        price: 30.0
    },
    book2: {
        title: "Hitch-hiker's guide to the galaxy",
        price: 42.0
    }
}

output application/json
---
{ 
    // Transform object books to array with object 
    // containing fields with index, key and book details
    booksArray: books pluck ((book, key, index) -> {position: index, key: key} ++ book),

    // We can easily find all titles from the object using pluck.
    // We cannot use books.*title as books is an object not an array.
    // Alternatives to get the same result is to use valuesOf function,
    // to get all book objects and then map to get the title:
    // * valuesOf(books) map (book) -> book.title
    // * valuesOf(books).title
    bookTitles: books pluck (book) -> book.title,

    // The pluck function also allows the dollar-sign to reference the value.
    // $$ is the key and $$$ the index.
    bookPrices: books pluck $.price
}

Output

{
  "booksArray": [
    {
      "position": 0,
      "key": "book1",
      "title": "Lord of the rings",
      "price": 30.0
    },
    {
      "position": 1,
      "key": "book2",
      "title": "Hitch-hiker's guide to the galaxy",
      "price": 42.0
    }
  ],
  "bookTitles": [
    "Lord of the rings",
    "Hitch-hiker's guide to the galaxy"
  ],
  "bookPrices": [
    30.0,
    42.0
  ]

In the next example we add an if/else to the lambda:

Source

%dw 2.0

var messages = {
  "message0": {
    "text": "Hi, mrhaki"
  },
  "message1": {
    "text": "Good evening, Hubert"
  },
  "message3": {
    "text": "Hello, DataWeave"
  },
  "created_with": "DataWeave 2.4"
}

output application/json
---
messages pluck ((value, key, index) -> if (key ~= "created_with") value else value.text)

Output

[
  "Hi, mrhaki",
  "Good evening, Hubert",
  "Hello, DataWeave",
  "DataWeave 2.4"
]

Written with DataWeave 2.4.