Reputation: 607
I want to convert an object structure to a structure which the Json-rules-engine can use.
I have this array as input, where A, B, C, D and E are some arbitrary condition.
INPUT
[
{
operator: 'any',
conditions: [
{
operator: 'all',
conditions: [
{ operator: 'all', conditions: [ A, B ] },
{ operator: 'any', conditions: [ C, D ] }
]
},
E
]
}
]
I want to reach an output in the following structure:
{
any: [E,
{
all: [{
all: [A, B],
any: [C, D]
}],
}
]
}
I am pretty sure that I need a recursive function for this. I have already tried the following. The problem here is that the output is overwritten, while I want it to be expanded when the recursive function reaches deeper levels of the array.
recursive(input, output) {
input.forEach((el) => {
if (typeof el !== "number") {
output[el.operator] = el.conditions
this.recursive(el.conditions, output);
}
});
}
Thanks in advance!
Upvotes: 0
Views: 231
Reputation: 135227
Adding my solution to the mix of other answers here. This transform
does a simple type analysis on the input t
and has excellent readability -
function transform (t)
{ switch (t?.constructor)
{ case Object:
return { [t.operator]: transform(t.conditions) }
case Array:
return t.map(transform)
default:
return t
}
}
const input =
[{operator: 'any', conditions: [{operator: 'all', conditions: [{operator: 'all', conditions: ['A', 'B']}, {operator: 'any', conditions: ['C', 'D']}]}, 'E']}]
console.log(transform(input))
Because input
is wrapped in an array, [...]
, the output is also wrapped -
[
{
"any": [
{
"all": [
{
"all": [
"A",
"B"
]
},
{
"any": [
"C",
"D"
]
}
]
},
"E"
]
}
]
If you'd like to strip the outer array, you can either unwrap the input, transform(input[0])
or unwrap the output, transform(input)[0]
.
Upvotes: 2
Reputation: 50797
Here's a very simple function designed to transform one element of your input. As mentioned in the comments, I don't understand what the outer array in the input is for, and why there is no corresponding one in the output. But if you need to, you can just map
this function over the input. (If they are supposed to fold into a single object, I think you need to explain how you would like that done.)
const transform = (x) =>
Object (x) === x && 'operator' in x
? {[x .operator]: (x .conditions || []) .map (transform)}
: x
const input = [{operator: 'any', conditions: [{operator: 'all', conditions: [{operator: 'all', conditions: ['A', 'B']}, {operator: 'any', conditions: ['C', 'D']}]}, 'E']}]
console .log (transform (input [0]))
.as-console-wrapper {max-height: 100% !important; top: 0}
It also does not change the condition order, which your output seems to want. (Because E
comes first.) If you do want to reorder them, what's the requirement?
Upvotes: 2
Reputation: 136114
I split this into two methods as I think it reads a bit easier, but you could combine them if you wanted. Note that A
,B
etc I needed to make a string to make this runnable.
const convertObj = (obj) => {
return {[obj.operator]: convertConditions(obj.conditions)}
}
const convertConditions = (arr) => {
return arr.map(i => {
if(typeof i == "string") {
return i
}else{
return convertObj(i);
}
})
}
Live example:
var input = [{
operator: 'any',
conditions: [{
operator: 'all',
conditions: [{
operator: 'all',
conditions: ["A", "B"]
},
{
operator: 'any',
conditions: ["C", "D"]
}
]
},
"E"
]
}]
const convertObj = (obj) => {
return {[obj.operator]: convertConditions(obj.conditions)}
}
const convertConditions = (arr) => {
return arr.map(i => {
if(typeof i == "string") {
return i
}else{
return convertObj(i);
}
})
}
var result = convertObj(input[0]);
console.log(result);
Upvotes: 1