Open pepijnolivier opened 2 years ago
I am running into the same issue.
I ended up working around the issue by defining the field with just the root array json path (eg $.items
rather than $.items[?(@.type=='Food')]
) and using a wrapper component to handle the create or update functionality.
It's a workaround, but gets the job done. Just FYI for anyone else struggling with this (@dsdavis4)
I'm having a similar issue trying to set a property in an object which doesn't already exist in the object. So I wrote a function as a workaround. Essentially I initialize each property that doesn't exist in the object before setting the final value. This probably doesn't handle all the edge cases but I think a similar approach could be taken for arrays where you push a new item onto the array.
function setValueOnNewProperty(theObject, newValue) {
let paths = jp.paths(theObject, path);
const parsed = jp.parse(path);
const queue = [];
let shorterPath = '';
// find a path that does exist on the object
while (paths.length === 0) {
queue.push(parsed.pop());
shorterPath = jp.stringify(parsed);
paths = jp.paths(theObject, shorterPath);
}
// build up the object to set the value
while (queue.length > 0) {
const subPath = queue.pop();
const newPath = subPath.expression.value;
// need to initialize every property that doesn't already exist on the object
const currentValue = jp.value(theObject, shorterPath);
currentValue[newPath] = {}
jp.value(theObject, shorterPath, currentValue);
parsed.push(subPath);
shorterPath = jp.stringify(parsed);
// at the end of reconstructing the path -> set the final/new value
if (queue.length === 0) {
jp.value(theObject, shorterPath, newValue);
}
}
}
If it may be of any use to someone: this is a further work on @drc-nloftsgard workaround that:
` const JSON_PATH_ROOT = "$"; function setValueOnNewProperty(theObject, path, newValue) { let paths = jp.paths(theObject, path);
const parsed = jp.parse(path);
const queue = [];
let shorterPath = '';
// find a path that does exist on the object
while (paths.length === 0) {
queue.push(parsed.pop());
shorterPath = jp.stringify(parsed);
paths = jp.paths(theObject, shorterPath);
}
// build up the object to set the value
while (queue.length > 0) {
const subPath = queue.pop();
const newPath = subPath.expression.value;
// need to initialize every property that doesn't already exist on the object
if (shorterPath === JSON_PATH_ROOT)
{
// root, see https://github.com/dchester/jsonpath/issues/72
jp.value(theObject, "$")[newPath] = {}
}
else
{
jp.apply(theObject, shorterPath, function(elem) {
elem[newPath] = {}
return elem
})
}
parsed.push(subPath);
shorterPath = jp.stringify(parsed);
// at the end of reconstructing the path -> set the final/new value
if (queue.length === 0) {
jp.apply(theObject, shorterPath, x => newValue);
return
}
}
// When property exists
jp.apply(theObject, path, x => newValue);
}`
So basically I have a javascript data object that might or might not contain an array entry for the jsonpath. I would like to use
jp.value(data, path, value)
and have it update the value in the array if it exists - or create it if it doesn't.Updating it this way works fine, but something odd is happening during create.
Proof of concept:
Output
☝️ You'll see that in the second example, the data is created inside the array... But not exactly with the right jsonpath. Somehow the jsonpath ends up as an object key. Is there any way I can make it so that the data is correctly appended to the array as I would expect it to ?
Thanks for any directions