JsonpathToAccess (jsonpath_to_access v0.1.0)

This module provides a function to convert a JSONPath expression into an access path. This library does not support all of jsonpath:

  • the .. operator is not supported because it can't be expressed using Access functions (that I know of)
  • all the functions like length for the same reason as above

There are two main methods:

Convert the JSONPath expression into an access path. This function is used by the get_in/2 function. You have to specify upfront if the data contains atom keys or not. You can cache or put the convert in a module attribute.

iex> path = JsonpathToAccess.convert!("$.store.book[0].author", to_atoms: true)
iex> JsonpathToAccess.get_in(%{store: %{book: [%{author: "Gandalf"}]}}, path)
"Gandalf"
defmodule MyModule do
  @json_path JsonpathToAccess.convert!("$.store.book[0].author")

  def my_lookup(data) do
    # or you can use the normal get_in if you don't use absolute path filter.
    JsonpathToAccess.get_in(data, @json_path)
  end
end

Just lookup the value in a map using the JSONPath expression.

iex> JsonpathToAccess.lookup(%{store: %{book: [%{author: "Gandalf"}]}}, "$.store.book[0].author")
{:ok, "Gandalf"}

Summary

Functions

Converts a JSONPath into an Access path. This can be used later with the JsonpathToAccess.get_in/2 function.

Converts a JSONPath into an Access path. This can be used later with the JsonpathToAccess.get_in/2 function.

The missing fetch_in function from Kernel.

Similar to Kernel.get_in/2, but it resolves the absolute values.

Looks up data using a JSONPath.

Types

Link to this type

access_path()

@type access_path() :: list()
@type operator() ::
  :equals | :not_equals | :lesser | :greater | :lesser_equals | :greater_equals
@type options() :: keyword()

Functions

Link to this function

convert(jsonpath, opts \\ [])

@spec convert(binary(), options()) :: {:ok, access_path()} | {:error, binary()}

Converts a JSONPath into an Access path. This can be used later with the JsonpathToAccess.get_in/2 function.

iex> {:ok, access_path} = JsonpathToAccess.convert("$.a.b")
iex> JsonpathToAccess.get_in(%{"a" => %{"b" => "value"}}, access_path)
"value"
iex> {:ok, access_path} = JsonpathToAccess.convert("$.a.b", to_atoms: true)
iex> JsonpathToAccess.get_in(%{a: %{b: "value"}}, access_path)
"value"
Link to this function

convert!(jsonpath, opts \\ [])

@spec convert!(binary(), options()) :: access_path()

Converts a JSONPath into an Access path. This can be used later with the JsonpathToAccess.get_in/2 function.

iex> access_path = JsonpathToAccess.convert!("$.a.b")
iex> JsonpathToAccess.get_in(%{"a" => %{"b" => "value"}}, access_path)
"value"
iex> access_path = JsonpathToAccess.convert!("$.a.b", to_atoms: true)
iex> JsonpathToAccess.get_in(%{a: %{b: "value"}}, access_path)
"value"
Link to this function

fetch_in(data, keys)

@spec fetch_in(Access.t(), [term(), ...]) :: {:ok, term()} | :error

The missing fetch_in function from Kernel.

Probably not exactly what you want, internally used for looking up if a value exists in a nested map.

Link to this function

get_in(data, access)

@spec get_in(Access.t(), access_path()) :: term() | nil

Similar to Kernel.get_in/2, but it resolves the absolute values.

Link to this function

lookup(data, jsonpath)

@spec lookup(Access.t(), binary()) :: {:ok, term()} | {:error, binary()}

Looks up data using a JSONPath.

iex> JsonpathToAccess.lookup(%{"a" => %{"b" => 1}}, "$.a.b")
{:ok, 1}
iex> JsonpathToAccess.lookup(%{a: %{b: 1}}, "$.a.b")
{:ok, 1}
iex> JsonpathToAccess.lookup([a: [[b: 1], [b: 2], [b: 3]]], "$.a[?(@.b >= 2)].b")
{:ok, [2, 3]}