I have this Flattened Object
{
"abc.def.ghi": "foo",
"abc.def.jkl": "bar"
}
I want to write a dataweave to convert it into the original object, i.e.
{
"abc": {
"def": {
"ghi": "foo",
"jkl": "bar"
}
}
}
I am trying to avoid hard coding the keys because it is a quite large object, So I do not want something like this:
%dw 2.0
var test = {
"abc.def.ghi": "foo",
"abc.def.jkl": "bar"
}
output application/json
---
{
abc: {
def: {
ghi: test."abc.def.ghi",
jkl: test."abc.def.jkl"
}
}
}
Can I use some combination of available dataweave functions for achieving this?
Here is what I have tried so far:
%dw 2.0
var test = {
"abc.def.ghi": "foo",
"abc.def.jkl": "bar"
}
output application/json
---
test mapObject ((value, key) ->
(key as String splitBy ".")[-1 to 0]
reduce ((item, acc = value) ->
(item): acc
/*
First item=ghi,acc=foo => acc = {ghi: "foo"}
next item=def, acc={ghi: "foo"} => acc={def:{ghi:"foo"}}
*/
)
)
But this would generate some kind of separate pair of the nested JSON. Here is the output of the above code:
{
"abc": {
"def": {
"ghi": "foo"
}
},
"abc": {
"def": {
"jkl": "bar"
}
}
}
This is similar to @olamiral solution, but simplified and supports arrays.
%dw 2.0
output application/json
// Creates a array of key-value tuples with the object structure.
// I was not able to use entriesOf() because I had to modify the key to split it
var tuples = payload pluck ((value, key, index) ->
{
k: key splitBy("."),
v: value}
)
// Using groupBy, group the childs and maps to an object structure.
fun flatToObject(tuples, index) =
(tuples groupBy $.k[index]) mapObject ((groupedTuples, key, idx) ->
if(groupedTuples[0].k[index + 1]?)
// Has more levels
{ (key): flatToObject(groupedTuples,index + 1) }
else
// It's a leaf
{ (key): if (sizeOf(groupedTuples.v) > 1)
// It has an array of values
groupedTuples.v
else
// It has a single value
groupedTuples.v[0]
}
)
---
flatToObject(tuples,0)
With this payload:
{
"abc.def.ghi": "foo",
"abc.def.jkl": "bar",
"abc.de.f": "bar2",
"abc.def.jkm": "bar3",
"abc.de.f": 45
}
It's producing this output:
{
"abc": {
"def": {
"ghi": "foo",
"jkl": "bar",
"jkm": "bar3"
},
"de": {
"f": ["bar2", 45]
}
}
}
This solution does not support mixing simple values and objects in the same array.