How is the tilde escaping in the JSON Patch RFC supposed to operate?

2.2k Views Asked by At

Referencing https://www.rfc-editor.org/rfc/rfc6902#appendix-A.14:

A.14. ~ Escape Ordering

An example target JSON document:

{
  "/": 9,
  "~1": 10
}

A JSON Patch document:

[
  {"op": "test", "path": "/~01", "value": 10}
]

The resulting JSON document:

{
  "/": 9,
  "~1": 10
}

I'm writing an implementation of this RFC, and I'm stuck on this. What is this trying to achieve, and how is it supposed to work?

Assuming the answer to the first part is "Allowing json key names containing /s to be referenced," how would you do that?

3

There are 3 best solutions below

0
On BEST ANSWER

I think the example provided in RFC isn't exactly best thought-out, especially that it tries to document a feature only through example, which is vague at best - without providing any kind of commentary.

You might be interested in interpretation presented in following documents:

These seem awfully similar and I think it's due to nature of relation between Rackspace and OpenStack:

OpenStack began in 2010 as a joint project of Rackspace Hosting and NASA (...)

It actually provides some useful details including grammar it accepts and rationale behind introducing these tokens, as opposed to the RFC itself.

Edit: it seems that JSON pointers have separate RFC 6901, which is available here and OpenStack and Rackspace specifications above are consistent with it.

0
On

~0 expands to ~ so /~01 expands to /~1

I guess they mean that you shouldn't "double expand" so that expanded /~1 should not be expanded again to // and thus must not match the documents "/" key (which would happen if you double expanded). Neither should you expand literals in the source document so the "~1" key is literally that and not equivalent to the expanded "/". But I repeat that's my guess about the intention of this example, the real intention may be different.

The example is indeed really bad, in particular since it's using a "test" operation and doesn't specify the result of that operation. Other examples like the next one at A.15 at least says its test operation must fail, A.14 doesn't tell you if the operation should succeed or not. I assume they meant the operation should succeed, so that implies /~01 should match the "~1" key. That's probably all about that example.

If I were to write an implementation I'd probably not worry too much about this example and just look at what other implementations do - to check if I'm compatible with them. It's also a good idea to look for test suites of other projects, for example I found one from http://jsonpatch.com/ at https://github.com/json-patch/json-patch-tests

1
On

The ~ character is a keyword in JSON pointer. Hence, we need to "encode" it as ~0. To quote jsonpatch.com,

If you need to refer to a key with ~ or / in its name, you must escape the characters with ~0 and ~1 respectively. For example, to get "baz" from { "foo/bar~": "baz" } you’d use the pointer /foo~1bar~0

So essentially,

[
  {"op": "test", "path": "/~01", "value": 10}
]

when decoded yields

[
  {"op": "test", "path": "/~1", "value": 10}
]