jmespath.py icon indicating copy to clipboard operation
jmespath.py copied to clipboard

Ability to set and delete based on a jmespath

Open smilledge opened this issue 8 years ago • 6 comments

For example if I had following dict;

data = {
    "foo": {
        "bar": [
            {"name": "one"}, 
            {"name": "two"}
        ]
    }
}

I'd like to be able to change the value of "one" to "three" be using something like;

new_data = jmespath.replace('foo.bar[1].name', 'three', data)

And then remove the first item of the "bar" list;

new_data = jmespath.remove('foo.bar[1]', data)

smilledge avatar Feb 18 '17 22:02 smilledge

I too would be interested in deletion but rather as part of the language. Something like this:

jmespath.search('foo.bar | delete(name)', data)

The above would (rather unexcitingly) produce two empty dictionaries. However the potential is exciting - if those dictionaries had started out with all manner of other keys those other keys would be preserved!

bitdivine avatar Apr 05 '17 21:04 bitdivine

I note that there is some discussion about having a to_items() function that converts a dictionary into a list of key,value pairs. If that happens, and there is presumably also a matching from_items(), then what you are asking could be done with to_items(@) | [?[0]!='bar'] | from_items(@). However we are talking about a hypothetical future.

bitdivine avatar Apr 06 '17 22:04 bitdivine

Did anything happen to this? We are needing to look into using a jq binding instead entirely because this is missing :(

xeor avatar May 08 '19 08:05 xeor

I was also looking for this ability, but it may not fit well with jmespath. I'm thinking glom might be a better alternative: https://glom.readthedocs.io/en/latest/

kvancamp avatar Jun 15 '19 15:06 kvancamp

This is a feature great to have. Currently have to pipe to jq as a workaround.

Given the input

{
    "foo": {
        "bar": [
            {
                "name": "one"
            },
            {
                "name": "two"
            }
        ]
    }
}

To set: .foo.bar[1].name="three"

{
  "foo": {
    "bar": [
      {
        "name": "one"
      },
      {
        "name": "three"
      }
    ]
  }
}

To delete: del(.foo.bar[1])

{
  "foo": {
    "bar": [
      {
        "name": "one"
      }
    ]
  }
}

jiasli avatar Mar 02 '20 13:03 jiasli

Can this be considered for any upcoming improvements?

caffeinatedMike avatar Jun 10 '21 15:06 caffeinatedMike