json-patch / json-patch2

A possibile revision to the JSON-Patch format
44 stars 0 forks source link

Adding support for multiple selection/update #23

Open geryogam opened 5 years ago

geryogam commented 5 years ago

A core feature that is missing in JSON Pointer/JSON Patch specifications in my opinion is the ability to select/update multiple array or object items with a single path expression.

It would for instance solve issue #21 elegantly.

Motivation

Before knowing about JSON Pointer/JSON Patch, I developed a Python tool to update a few hundreds of JSON at work. I chose a JSON Patch-like approach. For selecting the nodes of JSON documents, I did not want to write my own path expression parser so I used Kenn Knowles’ JSON Path RW Python library that implements Stefan Goessner’s JSON Path specification (which has no official RFC at the moment). And it worked quite well for our needs.

The main reason why I based my tool on JSON Path was because it allows for multiple selection of array or object items. And the alternative of using multiple patch operations on single items was not an option, as the array and object sizes were not known in advance (they were different for each JSON document). So rebasing my tool on JSON Pointer instead of JSON Path for path expressions is currently not possible.

Examples

Here are two examples of what could be achieved by adding support for

in path expressions of JSON Pointer/JSON Patch.

I have used the add operator but array slice and object globbing should also work with the other operators of course (remove, replace, move, etc.).

Array slice

Target JSON document:

[
  {"foo": "bar"},
  {"foo": "bar"},
  {"foo": "bar"}
]

Patch JSON document:

[
  {"op": "add", "path": "/:/baz", "value": "qux"}
]

Resulting JSON document:

[
  {"foo": "bar", "baz": "qux"},
  {"foo": "bar", "baz": "qux"},
  {"foo": "bar", "baz": "qux"}
]

Object globbing

Target JSON document:

{
  "a": {"foo": "bar"},
  "b": {"foo": "bar"},
  "c": {"foo": "bar"}
}

Patch JSON document:

[
  {"op": "add", "path": "/*/baz", "value": "qux"}
]

Resulting JSON document:

{
  "a": {"foo": "bar", "baz": "qux"},
  "b": {"foo": "bar", "baz": "qux"},
  "c": {"foo": "bar", "baz": "qux"}
}
gregsdennis commented 5 years ago

Definitely agree with using JSON Path for multiple selection. If we proceed with this feature, my comments in https://github.com/json-patch/json-patch2/issues/1#issuecomment-467697586 and https://github.com/json-patch/json-patch2/issues/18#issuecomment-467702277 are moot.

The main reason why I based my tool on JSON Path was because it allows for multiple selection of array or object items.

👍

geryogam commented 5 years ago

@gregsdennis

Definitely agree with using JSON Path for multiple selection.

I think you meant JSON Pointer, as my proposal is to extend JSON Pointer to allow for multiple selection of array or object items, like JSON Path enables it already.

gregsdennis commented 5 years ago

@maggyero but JSON Pointer isn't controlled here. I'm not sure if you intend to update JSON Pointer, or if you intend to use a non-standard JSON Pointer.

My point is that there is already a syntax for selecting multiple values (JSON Path), so it should be used in JSON Patch in lieu of JSON Pointer.

geryogam commented 5 years ago

@gregsdennis I intend to update JSON Pointer. I don't want JSON Patch to use JSON Path because:

mitar commented 4 years ago

I feel this is going in the wrong direction and will make JSON patch be more and more like a programming language. I prefer to see JSON patch as a diff between known versions of JSON. Not a "program" to apply to unknown versions of JSON. The latter would then require more and more complicated logic. And how do we decide where it ends? Do you also want to define a function which computes the index at which to insert something? Or use regular expressions?

about-code commented 3 years ago

I feel this is going in the wrong direction and will make JSON patch be more and more like a programming language.

This might be a bit too pessimistic. It is more about adding a JSON query language rather than a programming language, e.g. something like a select key with a query expression as an alternative to the more limited path key.

@maggyero

Re: JSONPath: it has no RFC;

Very recently there are reliable indicators for this might to come :partying_face: (hurray):

Yet, I see a very strong contendor for JSONPath: James Saryerwinnie did an immensly good job with JMESPath which IMHO got even a bit ahead of JSONPath in quite a few important aspects:

  1. rigid and formal language definition worth to be called a specification
    • unfortunately neither standardized by a standards organization
  2. a reference-test-suite for implementors to prove conformance of their implementations
  3. implementations accross the most popular programming languages proven to be interoperable by passing the reference test suite
    • having only a few but high quality implementations is not a disadvantage

Hopefully, interoperability of JSONPath implementations will improve once it is officially standardized. JSONPath has had a strong influence on SQL:2016 and "SQL/JSON-Path" which is being incorporated into systems such as PostgreSQL. These are strong arguments for JSONPath to succeed in the long run, even though it's formally not the same as "SQL/JSON-Path".

I can't seriously elaborate on the formal properties of the languages such as expressiveness or computational complexity, but both seem to be expressive enough to cover a wide range of use cases. JSON-Patch2 would profit from incorporating any one of those.

gregsdennis commented 3 years ago

Repo for JSON Path formal specification development: https://github.com/jsonpath-standard/internet-draft

There is also a Slack workspace; links on the repo.

ubaumann commented 3 months ago

The RFC is published. Now would be an excellent time to support JSON Path in JSON Patch.

My primary use case would be to target maps inside a list based on a key-value pair and not use an index because the index could change.

mitar commented 3 months ago

Link to RFC?

ubaumann commented 3 months ago

https://datatracker.ietf.org/doc/rfc9535/