JSONPath-Plus / JSONPath

A fork of JSONPath from http://goessner.net/articles/JsonPath/
Other
963 stars 169 forks source link

Update the passed JSON Object #163

Open EarthyOrange opened 2 years ago

EarthyOrange commented 2 years ago

Motivation

Updating the passed JSON object

Current behavior

I don't think it exists

Desired behavior

JSONPath({ path: '..', json: {}, newValue: 'new' }); should update the json object with the new value at the location specified by the path.

brettz9 commented 2 years ago

If you set the option resultType to all, you should be able to use parent and parentProperty to do this.

EarthyOrange commented 2 years ago

@brettz9 Can you please give me an example on how to use this API? I went through the ReadMe again but the usage isn't very clear to me.

brettz9 commented 2 years ago

Here's an example where we set all of the items with a price greater than 18 to having a price of 30.

const json = {
    "store": {
        "book": [{
            "category": "reference",
            "author": "Nigel Rees",
            "title": "Sayings of the Century",
            "price": 8.95
        },
        {
            "category": "fiction",
            "author": "Evelyn Waugh",
            "title": "Sword of Honour",
            "price": 12.99
        },
        {
            "category": "fiction",
            "author": "Herman Melville",
            "title": "Moby Dick",
            "isbn": "0-553-21311-3",
            "price": 8.99
        },
        {
            "category": "fiction",
            "author": "J. R. R. Tolkien",
            "title": "The Lord of the Rings",
            "isbn": "0-395-19395-8",
            "price": 22.99
        }],
        "bicycle": {
            "color": "red",
            "price": 19.95
        }
    }
};

JSONPath({
    json,
    path: '$..[?(@.price && @.price > 18)]',
    resultType: 'all'
}).forEach(({parent, parentProperty}) => {
    // `parent` and `parentProperty` used together get us to the object which our
    //    path has matched, but we also need to specify the `price` property since we
    //    don't want to overwrite the whole object--only the object's `price`.
    parent[parentProperty].price = 30;
});
CharlieGreenman commented 2 years ago

@brettz9 this will not work recursively.

CharlieGreenman commented 2 years ago

I ended up using the json-pointer library in conjunction with pointer value to update json

Yiniau commented 2 years ago

this way work for me

const fieldsSlot = jp({
  path: `$..children[?(@.children == "#[slot(\\"FIELDS\\"\\)\\]")]`,
  json: template,
})

fieldsSlot[0].children = fields.map(formFieldTransfer)
EarthyOrange commented 1 year ago

@CharlieGreenman Thanks for the jsonpointer! Exactly what I was looking for.

CharlieGreenman commented 1 year ago

@CharlieGreenman Thanks for the jsonpointer! Exactly what I was looking for.

By all means

rattrayalex commented 1 year ago

Can't you do this?

const result = JSONPath({
    json,
    path: '$..[?(@.price && @.price > 18)]',
    resultType: 'all'
    callback: (value, _, { parent, parentProperty }) => {
      parent[parentProperty].price = 30
    },
})

of course, you could wrap this in a nice little helper:

const result = JSONPath({
    json,
    path: '$..[?(@.price && @.price > 18)].price',
    resultType: 'all'
    callback: updater(value => 30),
})

const updater = (cb) => (value, _, { parent, parentProperty }) => {
  return parent[parentProperty] = cb(value);
}