Elixir:通过嵌套JSON中的值前缀查找
问题描述:
我试图在嵌套的JSON响应中查找URL并映射它们。我的功能到目前为止是这样的:Elixir:通过嵌套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响应找?
答
你将不得不使用这个递归函数,它处理三种类型的数据:
- 在地图,它递归在其所有值。
- 对于列表,它遍历所有元素。
- 对于字符串,它选择以 “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"]
这是_brilliant_,对于大量的帮助来说非常重要。再次。 –