Эликсир: поиск по значению префикса во вложенном JSON
Я пытаюсь найти URL-адреса во вложенном ответе JSON и отобразить их. Моя функция до сих пор выглядит так:
def list(env, id) do
Service.get_document(env, id)
|> Poison.decode!
|> Enum.find(fn {_key, val} -> String.starts_with?(val, 'https') end)
end
JSON выглядит примерно так:
"stacks": [
{
"boxes": [
{
"content": "https://ddd.cloudfront.net/photos/uploaded_images/000/001/610/original/1449447147677.jpg?1505956120",
"box": "photo"
}
]
}
],
"logo": "https://ddd.cloudfront.net/users/cmyk_banners/000/000/002/original/banner_CMYK.jpg?1397201875"
Таким образом, URL могут иметь любой ключ и быть на любом уровне.
С этим кодом я получаю эту ошибку:
no function clause matching in String.starts_with?/2
Кто-нибудь есть лучший способ найти в ответах JSON?
1 ответ
Решение
Для этого вам придется использовать рекурсивную функцию, которая обрабатывает три типа данных:
- Для карты он повторяется по всем своим значениям.
- Для списка это рекурсивно по всем его элементам.
- Для строки выбираются строки, начинающиеся с "https"
Вот простая реализация, которая принимает термин и строку для проверки starts_with?
:
defmodule A do
def recursive_starts_with(thing, start, acc \\ [])
def recursive_starts_with(binary, start, acc) when is_binary(binary) do
if String.starts_with?(binary, start) do
[binary | acc]
else
acc
end
end
def recursive_starts_with(map, start, acc) when is_map(map) do
Enum.reduce(map, acc, fn {_, v}, acc -> A.recursive_starts_with(v, start, acc) end)
end
def recursive_starts_with(list, start, acc) when is_list(list) do
Enum.reduce(list, acc, fn v, acc -> A.recursive_starts_with(v, start, acc) end)
end
end
data = %{
"stacks" => [
%{
"boxes" => [
%{
"content" => "https://ddd.cloudfront.net/photos/uploaded_images/000/001/610/original/1449447147677.jpg?1505956120",
"box" => "photo"
}
]
}
],
"logo" => "https://ddd.cloudfront.net/users/cmyk_banners/000/000/002/original/banner_CMYK.jpg?1397201875"
}
data |> A.recursive_starts_with("https") |> IO.inspect
Выход:
["https://ddd.cloudfront.net/photos/uploaded_images/000/001/610/original/1449447147677.jpg?1505956120",
"https://ddd.cloudfront.net/users/cmyk_banners/000/000/002/original/banner_CMYK.jpg?1397201875"]