During transformation to JSON often I do not want null properties. It is easy to remove them, by just using skipNullOn attribute. However for empty objects it is not that trivial, especially when you have to deal with many such cases within one transformation. In this article I will show you how you can achieve this quick and easy.

Contract

Below you can see what we have as an input and what we expect. In our example we have complex.embedded.obj empty and  contents’ array with two empty objects. I would like to to easily remove them from output.

Transformation's expected output
Transformation’s expected output

You may ask yourself why this guy wants to remove empty objects. The answer is simple. During deserialization processes, engine may not handle correctly situation of empty object. It happened for a couple of times in projects that I have participated in.

Transformation

You can add emptiness condition separately for each occurrence. Although, for a lot of similar cases within one mapping it may be overwhelming and turn transformation in a little nightmare that is hard to read. That is why I have deiced to write dedicated recurrent function removing all empty objects from payload. Here is the code:

<br />
%dw 2.0<br />
output application/json skipNullOn=&quot;everywhere&quot;</p>
<p>fun notEmpty(elem) =<br />
  (elem default {}) != {}</p>
<p>fun filterEmptyObjects(elem) =<br />
  elem match {<br />
    case is Object -&gt; if(isEmpty(elem)) null else elem mapObject ($$): filterEmptyObjects($)<br />
    case is Array -&gt; elem map filterEmptyObjects($)<br />
    else -&gt; elem<br />
}<br />
---<br />
filterEmptyObjects(payload)</p>
<p>

Solution consists of two parts:

  • recurrent function traversing through each property within structure – filterEmptyObjects
  • conditional check if element is empty or not – notEmpty 

filterEmptyObjects function uses matching pattern – it is described in one of my previous blog posts and in MuleSoft documentation. Matching is used here to detect property type and handle it appropriately. When engine detects an object it check if it is empty. If not, we use mapObject to go through each object’s property.  For array DataWeave engine map each element. For all other cases we leave value as is.

What does this line do?

<br />
elem mapObject ($$): filterEmptyObjects($)<br />

I can rewrite it, to make it a little bit more easier to read.

<br />
elem mapObject {<br />
  ($$): filterEmptyObjects($)<br />
}<br />

Basically it maps one object into another one. mapObject goes through each property. In each cycle variable $ holds property’s value and $$ is property’s name. We preserver the same name and we assign to this field outcome from filterEmptyObjects function.

I can make this transformation still more readable like below:

<br />
elem mapObject (value, key) -&gt; {<br />
  (key): filterEmptyObjects(value)<br />
}<br />

However I prefer to keep my transformation short. You can look at this from the other side. When you have a longer transformation you can make it more succinct.

 

isEmpty function for DataWeave 1.0

In DataWeave 2.0 isEmpty function has been prepared. However for previous version no such function exists. You may use in that place below function

<br />
%funtion notEmpty(elem)<br />
  (elem default {}) != {}<br />

DataWeave – Tip #6 – empty JSON object
Tagged on:         

Leave a Reply

Your email address will not be published. Required fields are marked *