You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We've loved using the JSONPatch specification thus far and have built a number of internal and external APIs to use it. I wanted to get your thoughts on a few additions we will be pursuing to the JSONPatch spec (using a different content-type application/vnd.box.json-patch+json).
You are already aware of our desire for a strict-add operator and put it on the json-patch2 issue list. We are going to use patches to help us describe migrations on json which have a number of optional fields. We ended up wanting to make sure that everything made sense and was consistent with the existing set of operators and easy to reason about. Also we are contemplating a few new operators for dealing with paths with certain values.
Before I jump in, I realize this ups the complexity of the spec a bit, but we actually have need for each and everyone of these new operators and new modifiers. Some of the combinations of operators and modifiers aren't really needed for us, but we wanted to specify them fully to ensure that the convention we described actually generalizes properly.
Modifiers
The rule we've found when studying the existing operators is: Operators throw if source does not exist and do not care if dest exists or does not exist
What we are looking to do is add a number of new operators that follow this naming convention:
A suffix on operators for modifiers on source:
? = skip if source does not exist
A suffix on operators for modifiers on dest:
! = throws if dest exists
= skip if dest exists
Here's a helpful model for understanding:
add: { "op": "add", "path": "/foo", "value": "bar" } -- destination only
add -- overwrite dest either way
add! -- throw if dest is exists (aka the-one-true-add)
add* -- skip if dest exists (aka default operator)
remove: { "op": "remove", "path": "/foo" } -- source only
remove -- throw if source is missing otherwise delete
remove? -- skip if source is missing
replace: { "op": "replace", "path": "/foo", "value": "bar" } -- source only
replace -- throw if source is missing otherwise replace value
replace? -- skip if source is missing
copy: { "op": "copy", "from": "/foo", "path": "/bar" }
copy -- throws if source does not exist otherwise set or overwrite
copy? -- skips if source does not exist
copy! -- throws if dest already exists
copy* -- skips if dest already exists
ban: copy?! -- throw if dest exists or skip if source is missing
ban: copy?* -- skip if source does not exist or dest does exist
move: { "op": "move", "from": "/foo", "path": "/bar" }
move -- throws if source does not exist
move? -- skips if source does not exist
move! -- throws if source already exists, throws if dest already exists
move* -- skip if dest already exists
...
test: { "op": "test", "path": "/foo", "value": "bar" } -- source only
test -- throws if does not exist or is not equal value
test? - skips if source does not exist
!test -- throws if does not exist or value is equal, special.
!test? -- skip if source does not exist or throw if value is equal, special.
New Operators
We are also looking to add some new base operators: exists, translate, omit.
exists: { "op": "exists", "path": "/foo" } -- source only
exists -- throws if source does not exist
!exists -- throws if source exists, special.
translate: { "op": "translate", "path": "/foo", "from": "bar", "value": "baz" } -- source only
translate -- translates values at path that match "from" to "value"
translate? -- skip if source does not exist
omit: { "op": "omit", "path": "/foo", "value": "bar" } -- source only
omit -- remove the property or item if it matches value, throw if source does not exist
omit? -- skip if source does not exist
So yeah, I know you are pretty open to extensions as long as we are clear about the content-type. I'd just love any feedback you have about the design choices we've made so we can avoid deviating too much from any future plans you have.
The text was updated successfully, but these errors were encountered:
I think this is adding to much complexity to JSON patch. I think JSON patch should just provide a diff against a known version of base JSON and then external algorithms should be used to fuzzy-apply this if base JSON does not exactly match. I would suggest that JSON patch only standardizes some ways to provide more operation-level and global-level context to help with such fuzzy-apply algorithms.
The problem is that JSON is an array, Maybe we should make it an object with one property for steps of the patch, so:
{
"context": <value>,
"steps": [
...
]
}
This would make it much easier to extend. And add some global metadata to the whole set of steps. While additional metadata could go into each step as well.
We've loved using the JSONPatch specification thus far and have built a number of internal and external APIs to use it. I wanted to get your thoughts on a few additions we will be pursuing to the JSONPatch spec (using a different content-type application/vnd.box.json-patch+json).
You are already aware of our desire for a strict-add operator and put it on the json-patch2 issue list. We are going to use patches to help us describe migrations on json which have a number of optional fields. We ended up wanting to make sure that everything made sense and was consistent with the existing set of operators and easy to reason about. Also we are contemplating a few new operators for dealing with paths with certain values.
Before I jump in, I realize this ups the complexity of the spec a bit, but we actually have need for each and everyone of these new operators and new modifiers. Some of the combinations of operators and modifiers aren't really needed for us, but we wanted to specify them fully to ensure that the convention we described actually generalizes properly.
Modifiers
The rule we've found when studying the existing operators is:
Operators throw if source does not exist and do not care if dest exists or does not exist
What we are looking to do is add a number of new operators that follow this naming convention:
A suffix on operators for modifiers on source:
? = skip if source does not exist
A suffix on operators for modifiers on dest:
! = throws if dest exists
Here's a helpful model for understanding:
add: { "op": "add", "path": "/foo", "value": "bar" } -- destination only
add -- overwrite dest either way
add! -- throw if dest is exists (aka the-one-true-add)
add* -- skip if dest exists (aka default operator)
remove: { "op": "remove", "path": "/foo" } -- source only
remove -- throw if source is missing otherwise delete
remove? -- skip if source is missing
replace: { "op": "replace", "path": "/foo", "value": "bar" } -- source only
replace -- throw if source is missing otherwise replace value
replace? -- skip if source is missing
copy: { "op": "copy", "from": "/foo", "path": "/bar" }
copy -- throws if source does not exist otherwise set or overwrite
copy? -- skips if source does not exist
copy! -- throws if dest already exists
copy* -- skips if dest already exists
ban: copy?! -- throw if dest exists or skip if source is missing
ban: copy?* -- skip if source does not exist or dest does exist
move: { "op": "move", "from": "/foo", "path": "/bar" }
move -- throws if source does not exist
move? -- skips if source does not exist
move! -- throws if source already exists, throws if dest already exists
move* -- skip if dest already exists
...
test: { "op": "test", "path": "/foo", "value": "bar" } -- source only
test -- throws if does not exist or is not equal value
test? - skips if source does not exist
!test -- throws if does not exist or value is equal, special.
!test? -- skip if source does not exist or throw if value is equal, special.
New Operators
We are also looking to add some new base operators: exists, translate, omit.
exists: { "op": "exists", "path": "/foo" } -- source only
exists -- throws if source does not exist
!exists -- throws if source exists, special.
translate: { "op": "translate", "path": "/foo", "from": "bar", "value": "baz" } -- source only
translate -- translates values at path that match "from" to "value"
translate? -- skip if source does not exist
omit: { "op": "omit", "path": "/foo", "value": "bar" } -- source only
omit -- remove the property or item if it matches value, throw if source does not exist
omit? -- skip if source does not exist
So yeah, I know you are pretty open to extensions as long as we are clear about the content-type. I'd just love any feedback you have about the design choices we've made so we can avoid deviating too much from any future plans you have.
The text was updated successfully, but these errors were encountered: