2017-10-09 4 views
0

J'essaie de trouver des URL dans une réponse JSON imbriquée et les mapper. Ma fonction si loin ressemble à ceci:Elixir: recherche par valeur préfixe dans JSON imbriqué

def list(env, id) do 
    Service.get_document(env, id) 
    |> Poison.decode! 
    |> Enum.find(fn {_key, val} -> String.starts_with?(val, 'https') end) 
end 

Le JSON ressemble à peu près comme ceci:

"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" 

Ainsi, les URL peuvent avoir une clé, et être à tous les niveaux.

Avec ce code je reçois cette erreur:

no function clause matching in String.starts_with?/2 

Quelqu'un at-il une meilleure façon de trouver des réponses JSON?

Répondre

3

Vous devez utiliser la fonction récursive pour cela, qui gère trois types de données:

  1. Pour carte, il récursif sur toutes ses valeurs.
  2. Pour la liste, il récursse sur tous ses éléments.
  3. Pour chaîne, il sélectionne les chaînes qui commencent par "https"

Voici une implémentation simple qui accepte un terme et une chaîne pour vérifier avec 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 

Sortie:

["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"] 
+0

Ceci est _brilliant_, c'est tellement pour l'aide massive. Encore. –