【问题标题】:Elixir: find by value prefix in nested JSONElixir:在嵌套 JSON 中按值前缀查找
【发布时间】:2017-10-09 12:37:12
【问题描述】:

我正在尝试在嵌套的 JSON 响应中查找 URL 并对其进行映射。到目前为止,我的功能如下所示:

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 响应中查找?

【问题讨论】:

    标签: json elixir phoenix-framework elixir-poison


    【解决方案1】:

    您必须为此使用递归函数,它处理三种类型的数据:

    1. 对于 map,它会递归其所有值。
    2. 对于列表,它在其所有元素上递归。
    3. 对于字符串,它选择以“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"]
    

    【讨论】:

    • 这真是精彩,这对于大量的助攻来说实在是太棒了。再次。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-02
    • 2019-03-02
    • 2021-11-30
    • 2012-12-23
    相关资源
    最近更新 更多