Open fab-mindflow opened 3 years ago
I think you simply need to wrap the $key in square brackets. so | { "i":"am here"}, [$key] |
. I can't say for sure with your example as it's a screenshot. FYI, the first icon on the right side of the header lets you create a sharable URL of your example.
I'm playing around with a similar problem, and I've shared an example here: https://try.jsonata.org/EA_jo9zN7 (in this one, I hard-code the key value to be deleted).
I've been unable to resolve it, as [$key]
doesn't evaluate to a string, and I can't figure out how to get it to spit out the name of $key
. Here it is with [$key]
: https://try.jsonata.org/aki1aZlvG
In my case, I want to actually delete $key2
, so I've got three problems:
Description.Colour
in this case) to solely delete a child of a specific property.$key.$key2
when setting the value of "New Colour Key"
@lepinsk please could you paste the resultant JSON that you are trying to generate from this input data? That will help us understand what you are trying to achieve. Thanks.
@mindflow-aws, as Mark suggested, please could you paste a link to the jsonata exerciser rather than a screenshot and also the result you are trying to achieve. Thanks.
@andrew-coleman Sorry, that should have been included in my initial message. 🤦🏼♂️
Very broadly, I'm trying to find keys of a specific name (lets say targetKey
) at arbitrary depths and move their values up to their parent level, so for example:
{
"someKey": {
"targetKey": "someval1"
},
"otherKey": {
"test": "yep"
},
"anotherKey": {
"anotherInner": {
"targetKey": "anotherval"
}
}
}
Would be transformed to:
{
"someKey": "someval1",
"otherKey": {
"test": "yep"
},
"anotherKey": {
"anotherInner": "anotherval"
}
}
I've tried things like: $ ~> | ** [$lookup('targetKey')] | {"this should be parent": $lookup('targetKey')}, ['targetKey'] |
(which I've saved here). This does find and identify targetKey
and its values, and delete targetKey
as expected, however I'm unable to walk one level up to insert a new value.
I'm aware of the %
parent operator, but it's not clear to me whether there's a way to use that in the transform's update parameter in order to walk up a level. (Conversely, if the head parameter is operating up a level, I'm unsure how to pass a deletion that walks down one level and deletes a child, as it looks like deletion expects a string that matches a key at the same depth that the transform is operating.)
The transform operator doesn't work recursively. Probably best write a recursive function that does what you need, such as this:
(
$promote := function($obj) {
$each($obj, function($v,$k){
{$k: ($v.targetKey ? $v.targetKey : $v[*] ? $promote($v) : $v)}
}) ~> $merge()
};
$promote($)
)
It uses the $each() ~> $merge() pattern to work on name/values pairs individually. If the value contains a targetKey property, then it uses the value of that, otherwise if it's another object, it processes that recursively, and if it's not an object, it just uses that value.
@andrew-coleman Incredible — thanks so much for this. (And for the great work on JSONata!)
@andrew-coleman I found one edge case that I wanted to address here, in the event that someone else stumbles on this thread.
This will fail on any data structure that contains arrays within it, I believe because $each
presumes it's always operating on objects (Argument 1 of function "each" does not match function signature
).
I've handled that case (I think) with the following modification (available to test here):
(
$promote := function($obj) {
$type($obj) = "array" ? (
[$map($obj, $promote)]
) : (
$each($obj, function($v,$k){
{$k: ($v.targetKey ? $v.targetKey : $v[*] ? $promote($v) : $v)}
}) ~> $merge()
)
};
$promote($)
)
I'm using a $type
conditional test to decide whether to iterate through the values using $map
(in the case of an array), or proceed to $each
as usual. (I'm enclosing the return from $map
in square brackets to ensure that it doesn't convert single-element arrays to objects.)
Hi,
I'm struggling to use the transform operator to delete a key without knowing its name (the string can't be static in my use case). Is this possible? Can I use a @ context variable binding with transform operator in order to delete the matching element? Are there other alternative?
Here is my example where I'd want to delete any key/value object at any level in the hierarchy (the example is just one level) whose
readOnly
property istrue
.Thanks, Fabrice