View Source JsonPtr (json_ptr v1.1.0)

Implementation of JSONPointer.

This module handles JSONPointers as an internal term representation and provides functions to manipulate the JSONPointer term and to use the representation to traverse or manipulate JSON data.

See: https://www.rfc-editor.org/rfc/rfc6901 for the specification.

Warning

Do not rely on the private internal implementation of JSONPointer, it may change in the future.

Link to this section Summary

Functions

rolls back the JsonPtr to the parent of its most distant leaf.

like backtrack/1, but raises if attempted to backtrack from the root.

Performs a each operation on the JSON data at the given pointer, analogous to Enum.each/2. Returns :ok when all iterations are complete

converts a path to a JsonPtr

converts a URI (or a URI-string) to a JsonPtr.

appends path to the JsonPtr. This may either be a t:String.t, a list of t:String.t.

Performs a map operation on the JSON data at the given pointer, analogous to Enum.map/2.

returns the last part of the pointer and the pointer without it.

Performs a reduction operation on the JSON data at the given pointer, analogous to Enum.reduce/3.

given some JSON data, resolves the content pointed to by the JsonPtr.

given some JSON data, resolves the content pointed to by the JsonPtr.

creates a JsonPtr to its path equivalent.

creates a URI.t/0 struct out of a JsonPtr.

updates nested JSON data at the location given by the JsonPtr.

Link to this section Types

@type json() ::
  nil
  | boolean()
  | String.t()
  | number()
  | [json()]
  | %{optional(String.t()) => json()}
@opaque t()

Link to this section Functions

@spec backtrack(t()) :: {:ok, t()} | :error

rolls back the JsonPtr to the parent of its most distant leaf.

iex> {:ok, ptr} = "/foo/bar" |> JsonPtr.from_path |> JsonPtr.backtrack
iex> JsonPtr.to_path(ptr)
"/foo"
@spec backtrack!(t()) :: t()

like backtrack/1, but raises if attempted to backtrack from the root.

Link to this function

each(pointer, data, fun)

View Source
@spec each(t(), json(), (t(), json() -> any())) :: :ok

Performs a each operation on the JSON data at the given pointer, analogous to Enum.each/2. Returns :ok when all iterations are complete

The iterator function will be passed the updated pointer and the data at that pointer.

iex> ptr = JsonPtr.from_path("/foo")
iex> JsonPtr.each(ptr, %{"foo" => ["bar", "baz"]}, fn ptr, data -> send(self(), {JsonPtr.to_path(ptr), data}) end)
:ok
iex> receive do data -> data end
{"/foo/0", "bar"}
iex> receive do data -> data end
{"/foo/1", "baz"}
@spec from_path(Path.t()) :: t()

converts a path to a JsonPtr

iex> JsonPtr.from_path("/") # the root-only case
[]
iex> JsonPtr.from_path("/foo/bar")
["foo", "bar"]
iex> JsonPtr.from_path("/foo~0bar/baz")
["foo~bar", "baz"]
iex> JsonPtr.from_path("/currency/%E2%82%AC")
["currency", "€"]
@spec from_uri(URI.t() | String.t()) :: t()

converts a URI (or a URI-string) to a JsonPtr.

iex> JsonPtr.from_uri("#/foo/bar")
["foo", "bar"]
iex> JsonPtr.from_uri("/foo/bar")
["foo", "bar"]
iex> JsonPtr.from_uri(%URI{path: "/foo/bar"})
["foo", "bar"]
iex> JsonPtr.from_uri(%URI{fragment: "/foo/bar", host: "elixir-lang.org"})
["foo", "bar"]
Link to this function

join(pointer, next_path)

View Source
@spec join(t(), String.t() | [String.t()]) :: t()

appends path to the JsonPtr. This may either be a t:String.t, a list of t:String.t.

iex> ptr = JsonPtr.from_path("/foo/bar")
iex> ptr |> JsonPtr.join("baz") |> JsonPtr.to_path
"/foo/bar/baz"
iex> ptr |> JsonPtr.join(["baz", "quux"]) |> JsonPtr.to_path
"/foo/bar/baz/quux"
@spec map(t(), json(), (t(), json() -> result)) :: [result] when result: term()

Performs a map operation on the JSON data at the given pointer, analogous to Enum.map/2.

The iterator function will be passed the updated pointer and the data at that pointer.

iex> ptr = JsonPtr.from_path("/foo")
iex> JsonPtr.map(ptr, %{"foo" => %{"bar" => "baz"}}, fn ptr, data -> {JsonPtr.to_path(ptr), data} end)
[{"/foo/bar", "baz"}]
iex> JsonPtr.map(ptr, %{"foo" => ["bar", "baz"]}, fn ptr, data -> {JsonPtr.to_path(ptr), data} end)
[{"/foo/0", "bar"}, {"/foo/1", "baz"}]
@spec pop(t()) :: {t(), String.t()} | :error

returns the last part of the pointer and the pointer without it.

iex> {rest, last} = "/foo/bar" |> JsonPtr.from_path |> JsonPtr.pop
iex> last
"bar"
iex> JsonPtr.to_path(rest)
"/foo"
iex> "/" |> JsonPtr.from_path |> JsonPtr.pop
:error
Link to this function

reduce(pointer, data, acc, fun)

View Source
@spec reduce(t(), json(), acc, (t(), json(), acc -> acc)) :: acc when acc: term()

Performs a reduction operation on the JSON data at the given pointer, analogous to Enum.reduce/3.

The iterator function will be passed the updated pointer, the data and the accumulator at that pointer.

iex> ptr = JsonPtr.from_path("/foo")
iex> JsonPtr.reduce(ptr, %{"foo" => %{"bar" => "baz"}}, %{}, &Map.put(&3, JsonPtr.to_path(&1), &2))
%{"/foo/bar" => "baz"}
iex> JsonPtr.reduce(ptr, %{"foo" => ["bar", "baz"]}, %{}, &Map.put(&3, JsonPtr.to_path(&1), &2))
%{"/foo/0" => "bar", "/foo/1" => "baz"}
Link to this function

resolve_json(data, pointer)

View Source
@spec resolve_json(data :: json(), t() | String.t()) ::
  {:ok, json()} | {:error, String.t()}

given some JSON data, resolves the content pointed to by the JsonPtr.

Note

the json pointer is the second parameter to this function.

iex> JsonPtr.resolve_json(true, "/")
{:ok, true}
iex> JsonPtr.resolve_json(%{"foo~bar" => "baz"}, "/foo~0bar")
{:ok, "baz"}
iex> JsonPtr.resolve_json(%{"€" => ["quux", "ren"]}, JsonPtr.from_path("/%E2%82%AC/1"))
{:ok, "ren"}
Link to this function

resolve_json!(data, pointer)

View Source
@spec resolve_json!(data :: json(), t() | String.t()) :: json()

given some JSON data, resolves the content pointed to by the JsonPtr.

Note

the json pointer is the second parameter to this function.

iex> JsonPtr.resolve_json!(true, "/")
true
iex> JsonPtr.resolve_json!(%{"foo~bar" => "baz"}, "/foo~0bar")
"baz"
iex> JsonPtr.resolve_json!(%{"€" => ["quux", "ren"]}, JsonPtr.from_path("/%E2%82%AC/1"))
"ren"
@spec to_path(t()) :: Path.t()

creates a JsonPtr to its path equivalent.

iex> JsonPtr.to_path(["foo", "bar"])
"/foo/bar"
iex> JsonPtr.to_path(["foo~bar", "baz"])
"/foo~0bar/baz"
iex> JsonPtr.to_path(["currency","€"])
"/currency/%E2%82%AC"
@spec to_uri(t()) :: URI.t()

creates a URI.t/0 struct out of a JsonPtr.

The JsonPtr is placed in the :fragment field of the URI.

iex> JsonPtr.to_uri(["foo", "bar"])
%URI{fragment: "/foo/bar"}
Link to this function

update_json!(object, list, transformation)

View Source
@spec update_json!(data :: json(), t(), (json() -> json())) :: json()

updates nested JSON data at the location given by the JsonPtr.

iex> ptr = JsonPtr.from_path("/foo/0")
iex> JsonPtr.update_json!(%{"foo" => [1, 2]}, ptr, &(&1 + 1))
%{"foo" => [2, 2]}
iex> JsonPtr.update_json!(%{"foo" => %{"0" => 1}}, ptr, &(&1 + 1))
%{"foo" => %{"0" => 2}}