Current section
Files
Jump to
Current section
Files
lib/ex_json_path.ex
#
# This file is part of ExJsonPath.
#
# Copyright 2019 Ispirata Srl
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
defmodule ExJsonPath do
def eval(map, path) when is_map(map) and is_binary(path) do
with {:ok, compiled} <- compile(path) do
eval(map, compiled)
end
end
def eval(map, compiled_path) when is_map(map) and is_list(compiled_path) do
recurse(map, compiled_path)
end
def compile(path) when is_binary(path) do
with charlist = String.to_charlist(path),
{:ok, tokens, _} <- :jsonpath_lexer.string(charlist) do
:jsonpath_parser.parse(tokens)
end
end
defp recurse(item, []) do
item
end
defp recurse(enumerable, [{:access, {op, path, value}} | t])
when is_list(enumerable) or is_map(enumerable) do
Enum.reduce(enumerable, [], fn entry, acc ->
item =
case entry do
{_key, value} -> value
item -> item
end
value_at_path = recurse(item, path)
if compare(op, value_at_path, value) do
[recurse(item, t) | acc]
else
acc
end
end)
|> Enum.reverse()
end
defp recurse(map, [{:access, a} | t]) when is_map(map) do
case Map.fetch(map, a) do
{:ok, next_item} -> recurse(next_item, t)
:error -> {:error, :no_match}
end
end
defp recurse(array, [{:access, a} | t]) when is_list(array) and is_integer(a) do
next_item = Enum.at(array, a)
recurse(next_item, t)
end
defp compare(op, value1, value2) do
case op do
:== ->
value1 == value2
:!= ->
value1 != value2
end
end
end