h2non / jsonpath-ng

Finally, a JSONPath implementation for Python that aims to be standard compliant. That's all. Enjoy!
Apache License 2.0
572 stars 85 forks source link

Add documentation on how to update and remove nodes #100

Closed KaiRoesner closed 8 months ago

KaiRoesner commented 2 years ago

The package documentation says it provides "the ability to update or removes nodes in the tree" but doesn't specify how this is done. Please add this to the documentation!

1wang-wood commented 1 year ago

use parse('exp').update(data, value)

KaiRoesner commented 1 year ago

What about removing nodes? Are there more useful functions that can be applied to a parsed JSONPath expression? Please add the info to the README!

ec-agmednet commented 1 year ago

I agree, been trying to find out how to remove elements in a list. I don't see any documentation from this project or the two it merged from. Looking at the code and PRs there is this open one for delete: https://github.com/h2non/jsonpath-ng/pull/43/

There is a comment saying it is the same as filter but it looks different to me, mutating the json with a del. @h2non any help would be much appreciated!

ec-agmednet commented 1 year ago

@KaiRoesner I was able to do this manually for a list of elements I wanted to remove data with a disabled=True flag from:

    import json
    from jsonpath_ng.ext import parse
    json_dict = {"l": [{"e": 1}, {"e": 2, "disabled": True}, {"e": 3}]}
    jp = parse('$..*[?(@.disabled = true)]')
    for path in jp.find(json_dict):
        # import pdb; pdb.set_trace()
        if path.value:
            index = path.path.index
            print(f'{path.context.full_path=} {index=} BEFORE:\n{json.dumps(json_dict, indent=2)}\n')
            del path.context.value[index]
            print(f'AFTER:\n{json.dumps(json_dict, indent=2)}\n')

hope this helps, similar could probably be done for dict keys...

gh-andre commented 1 year ago

Updated documentation or at least a few examples on how to manipulate dictionaries would be helpful indeed. Type hints would also go a long way as well.

After wading through the code, seems that the intended way to delete fields is via a callback. At least I couldn't find any alternative. Maybe I missed something.

doc = {"a": 1, "b": "X"}

c_jp = jsonpath_ng.parse("$.c")

c_jp.update_or_create(doc, 123)

print(doc)      # {'a': 1, 'b': 'X', 'c': 123}

c_jp.update(doc, 456)

print(doc)      # {'a': 1, 'b': 'X', 'c': 456}

def rm_field(value: Any, mydoc: Dict[str, Any], name: str) -> None:
    del mydoc[name]

c_jp.update(doc, rm_field)

print(doc)      # {'a': 1, 'b': 'X'}
KaiRoesner commented 8 months ago

Relates to #44 and #106 Fixed with commit #f5e8987