View Source Jsonpatch (Jsonpatch v2.2.0)

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

Types

t()

A valid Jsonpatch operation by RFC 6902

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

Functions

Link to this function

apply_patch(json_patch, target, opts \\ [])

View Source
@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"}}
Link to this function

apply_patch!(json_patch, target, opts \\ [])

View Source
@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)

Link to this function

diff(source, destination)

View Source

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"}
]