Description
Currently, the Relative JSON Pointer (RJP) specification only specifies how to evaluate an RJP with a document reference. This is actually challenging as typical in-memory representations of JSON documents do not have child-to-parent links.
[EDIT: See also #1236 for an alternative approach]
I am implementing this spec at the moment, and doing so in terms of resolving the RJP against a regular JSON Pointer, and then evaluating the JSON Pointer with added functionality to handle the use of #
to get the property name or index number rather than the value. This is much easier to implement and a natural analog of resolving URI references against base URIs.
For RJPs that do not use the #
feature, using the resolved pointer is identical to using a regular JSON Pointer.
Supporting the #
feature involves making certain that there is a value at the location, and then returning the last component of the JSON Pointer.
If this approach is supported [EDIT: In addition to the current approach], then the RJP spec also needs to specify what happens if the JSON Pointer involves a -
as an array index to which #
is applied. -
indicates one position beyond the end of the array in the instance. The JSON Pointer spec states:
Note that the use of the "-" character to index an array will always
result in [a lack of concrete value] error condition because by definition it refers to
a nonexistent array element. Thus, applications of JSON Pointer need
to specify how that character is to be handled, if it is to be
useful.
In this sense, RJP is an "application" of JSON Pointer. The interesting case here is if, after moving upwards (removing components from the base pointer per the initial number in the RJP), the last remaining component is -
. In this case, applying #
should produce the index of that hypothetical next array item:
Given:
- base pointer
/array/-/foo
- relative pointer
1#
- instance
{"array": [{"foo": 0}, {"foo": 1}, {"foo": 2}]}
The resolved JSON Pointer would be /array/-
, to which we would apply the #
operation, returning 3
(the length of the array, which is also the index of the hypothetical next value). This is a useful piece of information to be able to access.
Note that it does not matter that the full base JSON Pointer does not resolve to anything. Just that /array
must resolve to an actual array, so that -
has something to measure.
This brings up another difference in the relative-to-base-pointer approach, which is that the base pointer need not be valid against an instance. Only the resolved pointer (ignoring #
which is not part of regular JSON Pointer) must either point to an actual location in the document, or must end in -
applied to an actual array in the document as above.
This does mean that there are scenarios that are possible with this approach that are not possible if the base pointer must point to an actual location. We could restrict the base pointer to only ones that point to an actual location if we want to, but then this "give me the length of the array" feature is not possible.
As a side note, I have not found any standalone implementation of RJP in Python, and wonder if this is part of the reason why. It's hard to write a generic implementation of RJP as specified without essentially re-inventing JSON Pointer to track the initial location in the document. Otherwise you need a more complex data structure with parent links.
I am not sure what milestone to put on this. It is obviously bigger than a "patch" but it's not clear to me that RJP needs to be locked to the JSON Schema spec progress as a.) this is backwards-compatible, and b.) it has no impact on the JSON Schema metaschema.
Metadata
Metadata
Assignees
Type
Projects
Status