Mule LogoMule runtime 4.2.2 introduces two new modules: Tree and Values. This blog, Part 1,  will address the new Values module and touch briefly on the Tree module. Part 2 will go into more depth with the Tree module since it is a little more complex to use. It is worth investigating both of these modules since they can help us create robust Dataweave scripts, quickly and easily.

The Values module, like the Tree module, can create robust scripts because it can handle changes to the payload structure, often without requiring refactoring. How? Well, it works by automatically outputting new values in the payload keeping the initial structure intact, without having to know beforehand what the structure is. It traverses the input data while operating on payload values with autonomous functions.

 

Here are some example use cases:Nodes Definition

  • Desensitizing information when logging or processing data that may contain personal and  HIPAA-related data, such as names, date-of-birth, credit card data, and user passwords
  • Formatting data such as currency, dates, and enumeration types
  • Creating simple boolean expressions based on optional content or values 

Both modules can operate on JSON, Java, or XML payloads. As you will see in Part 2, the Tree module passes in a path object in addition to the current value to the autonomous function. The path object is a simple array of nodes (of PathElement type) that allows the autonomous function to know where it is as it traverses through the input or payload data. Object models, nodes, branches and leaves are all explained in Part 2. Here we will take a quick look at the Values module and briefly introduce the Tree module.

 

Desensitizing Data with Values.mask and Tree.mapLeafValues  Method

In our first example, imagine we have sensitive credit card data. When logging or passing this data along to some external system, we may wish to obfuscate or encrypt it. The payload below contains some sample data. 
 

{ “name”:“John Doe”,
  “address”:“123 State St, Auburn MA 01824”,
  “payment-info”:[
    {“type”:“CC”,
     “number”:“1231-1123-1231-1233”,
     “amount”12.10
    },
    {“type”:“GIFT_CARD”,
     “number”:“abc-123-def”,
     “amount”34.211
    }]
}

 

Using the following Dataweave script

%dw 2.0
output application/json
import * from dw::util::Values

payload mask field ( “number”) with “*******”

 

We get

{ “name”:“John Doe”,
  “address”:“123 State St, Auburn MA 01824”,
  “payment-info”:[
    {“type”:“CC”,
     “number”:“*******”,
     “amount”12.10
    },
    {“type”:“GIFT_CARD”,
     “number”:“*******”,
     “amount”34.211
    }]
}

 

There are a few things worth noting here. The first is that the “with” method took a simple string to replace the value. However, the original value is passed into this method using the autonomous argument “$”. We can use this argument to encrypt it or modify it. In this example we use the upper case function to change the case of the original gift card number.

Here is the original gift card number:
 

. . .  },
    {“type”:“GIFT_CARD”,
     “number”:“abc-123-def”,
     “amount”34.211
    }]
}

 

 

Using the Dataweave script with the autonomous $ argument.

%dw 2.0
output application/json
import * from dw::util::Values

payload mask field( “number”) with upper($)

 

We get

. . .  },
    {“type”:“GIFT_CARD”,
     “number”:“ABC-123-DEF”,
     “amount”34.211
    }]
}

The second thing to note is how this module handles change. For example, let’s say a new phone number field was added to the payload and the payment-info array is replaced with a simple (non-array) object.

{ “name”:“John Doe”,
  “address”:“123 State St, Auburn MA 01824”,
  “phone-number”:“214-555-1212”,
  “payment-info”: {
     “type”:“GIFT_CARD”,
     “number”:“abc-123-def”,
     “amount”34.211
    }
}

 

Using the same Dataweave script as before,

%dw 2.0
output application/json
import * from dw::util::Values

payload mask field( “number”) with upper ($)

 

It still works and returns the expected result with the new field and payment-info structure.

{ “name”:“John Doe”,
  “address”:“123 State St, Auburn MA 01824”,
  “phone-number”:“214-555-1212”,
  “payment-info”: {
     “type”:“GIFT_CARD”,
     “number”:“ABC-123-DEF”,
     “amount”34.211
    }
}

 

Obfuscating Data with Tree.mapLeafValues 

We can also get the same result if we use Tree.mapLeafValues. We start with the input payload as before.

 

{ “name”:“John Doe”,
  “address”:“123 State St, Auburn MA 01824”,
  “payment-info”:[
    {“type”:“CC”,
     “number”:“1231-1123-1231-1233”,
     “amount”12.10
    },
    {“type”:“GIFT_CARD”,
     “number”:“abc-123-def”,
     “amount”34.211
    }]
}

 

We can create the following Dataweave script with Tree method, mapLeafValues. (Note: this method is available after you import the Tree module as shown.)

%dw 2.0
output application/json
import * from dw::util::Tree

payload mapLeafValues (value, path)  ->
if (path[-1].selector==”number”)  (“*******”) else (value)

 

As you can see the result is the same as when we used the Values module.

{ “name”:“John Doe”,
  “address”:“123 State St, Auburn MA 01824”,
  “payment-info”:[
    {“type”:“CC”,
     “number”:“*******”,
     “amount”12.10
    },
    {“type”:“GIFT_CARD”,
     “number”:“*******”,
     “amount”34.211
    }]
}

 

So why do we need two modules?  It has to do with this path object. Notice that this path object is getting passed into the autonomous function and we can perform complex logic on it like this if-then-else statement.

if (path[-1].selector==”number”) (“*******”) else (value)
 
In Part 2, we will see how this can handle different types of changes at once with a single script and in a robust way. This will involve some details around the parsing of the input into this path object as you will see. 

 

Other Helpful Dataweave Links

Join the Conversation

About the Author