Skip to content

Commit

Permalink
docs: JSONPointer guide
Browse files Browse the repository at this point in the history
  • Loading branch information
jg-rp committed Jul 18, 2023
1 parent 525acfd commit a044a96
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 17 deletions.
135 changes: 135 additions & 0 deletions docs/pointers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# JSON Pointers

**_New in version 0.8.0_**

JSON Pointer ([RFC 6901](https://datatracker.ietf.org/doc/html/rfc6901)) is a string syntax for targeting a single value (JSON object, array or scalar) in a JSON document. Whereas a JSONPath has the potential to yield many values from a JSON document, a JSON Pointer can _resolve_ to at most one value.

JSON Pointers are a fundamental part of JSON Patch ([RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902)). Each patch operation must have at least one pointer, identifying the target value.

## `resolve(data)`

Resolve this pointer against _data_. _data_ can be a file-like object or string containing JSON formatted data, or a Python [`Mapping`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Mapping) or [`Sequence`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence), like a dictionary or list.

```python
from jsonpath import JSONPointer

example_data = {"foo": {"bar": [1, 2, 3]}}
pointer = JSONPointer("/foo/bar/0")

print(pointer.resolve(example_data)) # 1
```

## `resolve_parent(data)`

Resolve this pointer against _data_, return the object and its parent as a `(parent, object)` tuple.

If _object_ does not exist in _data_ but _parent_ does, `(parent, UNDEFINED)` will be returned. Where `jsonpath.pointer.UNDEFINED` indicates the lack of a value.

If this pointer points to the JSON document root, parent will be `None`.

```python
from jsonpath import JSONPointer

example_data = {"foo": {"bar": [1, 2, 3]}}

pointer = JSONPointer("/foo/bar/0")
print(pointer.resolve_parent(example_data)) # ([1, 2, 3], 1)

# 'thing' does not exist
pointer = JSONPointer("/foo/thing")
print(pointer.resolve_parent(example_data)) # ({'bar': [1, 2, 3]}, <jsonpath.pointer._Undefined object at 0x7f0c7cf77040>)

pointer = JSONPointer("")
print(pointer.resolve_parent(example_data)) # (None, {'foo': {'bar': [1, 2, 3]}})
```

## `exists(data)`

**_New in version 0.9.0_**

Return _True_ if this pointer can be resolved against _data_, or _False_ otherwise. Note that `JSONPointer.resolve()` can return legitimate falsy values that form part of the target JSON document. This method will return `True` if a falsy value is found.

```python
from jsonpath import JSONPointer

example_data = {"foo": {"bar": [1, 2, 3]}, "baz": False}

pointer = JSONPointer("/foo/bar/0")
print(pointer.exists()) # True

pointer = JSONPointer("/foo/bar/9")
print(pointer.exists()) # False

pointer = JSONPointer("/baz")
print(pointer.exists()) # True
```

## `join(*parts)`

**_New in version 0.9.0_**

Join this pointer with _parts_. Each part is expected to be a JSON Pointer string, possibly without a leading slash. If a part does have a leading slash, the previous pointer is ignored and a new `JSONPath` is created, and processing of remaining parts continues.

`join()` is equivalent to using the slash (`/`) operator for each argument.

```python
from jsonpath import JSONPointer

pointer = JSONPointer("/foo/bar")
print(pointer) # /foo/bar
print(pointer.join("baz")) # /foo/bar/baz
print(pointer.join("baz", "0")) # /foo/bar/baz/0
```

## `parent()`

**_New in version 0.9.0_**

Return this pointer's parent, as a new `JSONPointer`. If this pointer points to the document root, _self_ is returned.

```python
from jsonpath import JSONPointer

pointer = JSONPointer("/foo/bar")
print(pointer) # /foo/bar
print(pointer.parent()) # /foo
```

## `is_relative_to(pointer)`

Return _True_ if this pointer points to a child of the argument pointer, which must be a `JSONPointer` instance, or _False_ otherwise

```python
from jsonpath import JSONPointer

pointer = JSONPointer("/foo/bar")

another_pointer = JSONPointer("/foo/bar/0")
print(another_pointer.is_relative_to(pointer)) # True

another_pointer = JSONPointer("/foo/baz")
print(another_pointer.is_relative_to(pointer)) # False
```

## `relative(relative_pointer)`

**_New in version 0.9.0_**

TODO:

## Slash Operator

**_New in version 0.9.0_**

The slash operator allows you to create pointers that are children of an existing pointer.

```python
from jsonpath import JSONPointer

pointer = JSONPointer("/users")
child_pointer = pointer / "score" / "0"
another_child_pointer = pointer / "score/1"

print(child_pointer) # "/users/score/0"
print(another_child_pointer) # "/users/score/1"
```
17 changes: 0 additions & 17 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,23 +230,6 @@ print(sue_score) # 0

See also [`JSONPathMatch.pointer()`](api.md#jsonpath.match.JSONPathMatch.pointer), which builds a [`JSONPointer`](api.md#jsonpath.JSONPointer) from a `JSONPathMatch`.

### Slash Operator

**_New in version 0.9.0_**

The slash operator allows you to create pointers that are children of an existing pointer.

```python
from jsonpath import JSONPointer

pointer = JSONPointer("/users")
child_pointer = pointer / "score" / "0"
another_child_pointer = pointer / "score/1"

print(child_pointer) # "/users/score/0"
print(another_child_pointer) # "/users/score/1"
```

## `patch.apply(patch, data)`

**_New in version 0.8.0_**
Expand Down
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ nav:
- Guides:
- JSONPath Syntax: "syntax.md"
- Filter Functions: "functions.md"
- JSON Pointers: "pointers.md"
- Async Support: "async.md"
- API Reference:
- High Level API: "api.md"
Expand Down

0 comments on commit a044a96

Please sign in to comment.