View Source JsonPtr (json_ptr v1.2.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
Performs a flat_map operation on the JSON data at the given pointer, analogous
to Enum.flat_map/2
.
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
@opaque t()
Link to this section Functions
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"
like backtrack/1
, but raises if attempted to backtrack from the root.
@spec each(t(), json(), (t(), json() -> any())) :: :ok
@spec each(t(), json(), (t(), pos_integer() | String.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.
If you pass an arity 3 function, it will also pass the key (or index) of the data in addition to the JsonPtr.
iex> ptr = JsonPtr.from_path("/foo")
iex> JsonPtr.each(ptr, %{"foo" => ["bar", "baz"]}, &send(self(), {JsonPtr.to_path(&1), &2}))
:ok
iex> receive do data -> data end
{"/foo/0", "bar"}
iex> receive do data -> data end
{"/foo/1", "baz"}
iex> JsonPtr.each(ptr, %{"foo" => ["bar", "baz"]}, &send(self(), {JsonPtr.to_path(&1), &2, &3}))
:ok
iex> receive do data -> data end
{"/foo/0", 0, "bar"}
iex> receive do data -> data end
{"/foo/1", 1, "baz"}
@spec flat_map(t(), json(), (t(), json() -> [result])) :: [result] when result: term()
@spec flat_map(t(), json(), (t(), pos_integer() | String.t(), json() -> [result])) :: [result] when result: term()
Performs a flat_map operation on the JSON data at the given pointer, analogous
to Enum.flat_map/2
.
If you pass an arity 3 function, it will also pass the key (or index) of the data in addition to the JsonPtr.
The iterator function will be passed the updated pointer and the data at that pointer.
iex> ptr = JsonPtr.from_path("/foo")
iex> JsonPtr.flat_map(ptr, %{"foo" => %{"bar" => "baz"}}, fn ptr, data -> [{JsonPtr.to_path(ptr), data}] end)
[{"/foo/bar", "baz"}]
iex> JsonPtr.flat_map(ptr, %{"foo" => ["bar", "baz"]}, fn ptr, data -> [{JsonPtr.to_path(ptr), data}] end)
[{"/foo/0", "bar"}, {"/foo/1", "baz"}]
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", "€"]
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"]
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()
@spec map(t(), json(), (t(), pos_integer() | String.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.
If you pass an arity 3 function, it will also pass the key (or index) of the data in addition to the JsonPtr.
iex> ptr = JsonPtr.from_path("/foo")
iex> JsonPtr.map(ptr, %{"foo" => %{"bar" => "baz"}}, &{JsonPtr.to_path(&1), &2})
[{"/foo/bar", "baz"}]
iex> JsonPtr.map(ptr, %{"foo" => ["bar", "baz"]}, &{JsonPtr.to_path(&1), &2})
[{"/foo/0", "bar"}, {"/foo/1", "baz"}]
iex> JsonPtr.map(ptr, %{"foo" => %{"bar" => "baz"}}, &{JsonPtr.to_path(&1), &2, &3})
[{"/foo/bar", "bar", "baz"}]
iex> JsonPtr.map(ptr, %{"foo" => ["bar", "baz"]}, &{JsonPtr.to_path(&1), &2, &3})
[{"/foo/0", 0, "bar"}, {"/foo/1", 1, "baz"}]
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
@spec reduce(t(), json(), acc, (t(), json(), acc -> acc)) :: acc when acc: term()
@spec reduce(t(), json(), acc, (t(), pos_integer() | String.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.
If you pass an arity 4 function, it will also pass the key (or index) of the data in addition to the JsonPtr.
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"}
iex> JsonPtr.reduce(ptr, %{"foo" => %{"bar" => "baz"}}, %{}, &Map.put(&4, {JsonPtr.to_path(&1), &2}, &3))
%{{"/foo/bar", "bar"} => "baz"}
iex> JsonPtr.reduce(ptr, %{"foo" => ["bar", "baz"]}, %{}, &Map.put(&4, {JsonPtr.to_path(&1), &2}, &3))
%{{"/foo/0", 0} => "bar", {"/foo/1", 1}=> "baz"}
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"}
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"
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"
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"}
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}}