View Source Jsonpatch (Jsonpatch v2.2.1)
A implementation of RFC 6902 in pure Elixir.
The patch can be a single change or a list of things that shall be changed. Therefore a list or a single JSON patch can be provided. Every patch belongs to a certain operation which influences the usage.
According to RFC 6901 escaping of /
and ~
is done
by using ~1
for /
and ~0
for ~
.
Summary
Functions
Apply a Jsonpatch or a list of Jsonpatches to a map or struct. The whole patch will not be applied when any path is invalid or any other error occured. When a list is provided, the operations are applied in the order as they appear in the list.
Apply a Jsonpatch or a list of Jsonpatches to a map or struct. In case of an error it will raise an exception. When a list is provided, the operations are applied in the order as they appear in the list.
Creates a patch from the difference of a source map to a destination map or list.
Types
@type t() :: map() | Jsonpatch.Operation.Add.t() | Jsonpatch.Operation.Remove.t() | Jsonpatch.Operation.Replace.t() | Jsonpatch.Operation.Copy.t() | Jsonpatch.Operation.Move.t() | Jsonpatch.Operation.Test.t()
A valid Jsonpatch operation by RFC 6902
Functions
@spec apply_patch( t() | [t()], target :: Jsonpatch.Types.json_container(), Jsonpatch.Types.opts() ) :: {:ok, Jsonpatch.Types.json_container()} | {:error, Jsonpatch.Error.t()}
Apply a Jsonpatch or a list of Jsonpatches to a map or struct. The whole patch will not be applied when any path is invalid or any other error occured. When a list is provided, the operations are applied in the order as they appear in the list.
Atoms are never garbage collected. Therefore, Jsonpatch
works by default only with maps
which used binary strings as key. This behaviour can be controlled via the :keys
option.
Examples
iex> patch = [
...> %{op: "add", path: "/age", value: 33},
...> %{op: "replace", path: "/hobbies/0", value: "Elixir!"},
...> %{op: "replace", path: "/married", value: true},
...> %{op: "remove", path: "/hobbies/2"},
...> %{op: "remove", path: "/hobbies/1"},
...> %{op: "copy", from: "/name", path: "/surname"},
...> %{op: "move", from: "/home", path: "/work"},
...> %{op: "test", path: "/name", value: "Bob"}
...> ]
iex> target = %{"name" => "Bob", "married" => false, "hobbies" => ["Sport", "Elixir", "Football"], "home" => "Berlin"}
iex> Jsonpatch.apply_patch(patch, target)
{:ok, %{"name" => "Bob", "married" => true, "hobbies" => ["Elixir!"], "age" => 33, "surname" => "Bob", "work" => "Berlin"}}
iex> # Patch will not be applied if test fails. The target will not be changed.
iex> patch = [
...> %{op: "add", path: "/age", value: 33},
...> %{op: "test", path: "/name", value: "Alice"}
...> ]
iex> target = %{"name" => "Bob", "married" => false, "hobbies" => ["Sport", "Elixir", "Football"], "home" => "Berlin"}
iex> Jsonpatch.apply_patch(patch, target)
{:error, %Jsonpatch.Error{patch: %{"op" => "test", "path" => "/name", "value" => "Alice"}, patch_index: 1, reason: {:test_failed, "Expected value '\"Alice\"' at '/name'"}}}
iex> # Patch will succeed, not applying invalid path operations.
iex> patch = [
...> %{op: "replace", path: "/name", value: "Alice"},
...> %{op: "replace", path: "/age", value: 42}
...> ]
iex> target = %{"name" => "Bob"} # No age in target
iex> Jsonpatch.apply_patch(patch, target, ignore_invalid_paths: true)
{:ok, %{"name" => "Alice"}}
@spec apply_patch!( t() | [t()], target :: Jsonpatch.Types.json_container(), Jsonpatch.Types.opts() ) :: Jsonpatch.Types.json_container()
Apply a Jsonpatch or a list of Jsonpatches to a map or struct. In case of an error it will raise an exception. When a list is provided, the operations are applied in the order as they appear in the list.
(See Jsonpatch.apply_patch/2 for more details)
@spec diff(Jsonpatch.Types.json_container(), Jsonpatch.Types.json_container()) :: [ t() ]
Creates a patch from the difference of a source map to a destination map or list.
Examples
iex> source = %{"name" => "Bob", "married" => false, "hobbies" => ["Elixir", "Sport", "Football"]}
iex> destination = %{"name" => "Bob", "married" => true, "hobbies" => ["Elixir!"], "age" => 33}
iex> Jsonpatch.diff(source, destination)
[
%{path: "/married", value: true, op: "replace"},
%{path: "/hobbies/2", op: "remove"},
%{path: "/hobbies/1", op: "remove"},
%{path: "/hobbies/0", value: "Elixir!", op: "replace"},
%{path: "/age", value: 33, op: "add"}
]