Эликсир: извлечение элемента из больших структурированных данных - PullRequest
0 голосов
/ 10 июля 2020

Я сделал запрос на получение с помощью HTTPoison, но теперь я пытаюсь разобрать файл JSON. Для этого я использую библиотеку Poison. Но у меня возникли проблемы с получением элемента из объекта JSON.

Вот мой код:

def parse_json do
    IO.puts("\nLet's parse JSON file.")

    url = "https://entreprise.data.gouv.fr/api/sirene/v3/etablissements/?page=1&per_page=1&etat_administratif=A&denomination_usuelle=" <> "SAFENERGY"

    start()
    case get(url) do
      {:ok, %{status_code: 200, body: body}} ->
        IO.puts("Success research.")
        decode!(body)
        #|> Map.to_list() NON-FUNCTIONAL
        #|> Enum.find(&match?(["etablissements" | _], &1)) NON-FUNCTIONAL
        #|> Enum.find_value(fn %{"siren" => siren} -> siren end) NON-FUNCTIONAL
        #|> IO.puts(&(&1.siren)) NON-FUNCTIONAL
        |> IO.inspect()

      {:ok, %{status_code: 404}} ->
        IO.puts("None match between establishment's name and Sirene API.")

      {:ok, %{status_code: 500}} ->
        IO.puts("Nonfunctional Sirene API's server (maintenance...).")

      {:ok, %{status_code: 429}} ->
        IO.puts("Exceeding the maximum call volume (7 requests/s maximum).")

      {:error, %{reason: reason}} ->
        IO.puts("Failure research.")
        IO.inspect(reason)

      _ -> IO.puts("Unknown error! Good luck to find it!")
    end
  end

Мой вывод:

%{
  "etablissements" => [
    %{
      "statut_diffusion" => "O",
      "libelle_voie" => "MAS DES PERES",
      "distribution_speciale_2" => nil,
      "geo_ligne" => "G",
      "libelle_voie_2" => nil,
      "unite_legale_id" => 33014385,
      "type_voie_2" => nil,
      "geo_type" => "street",
      "code_postal_2" => nil,
      "libelle_pays_etranger" => nil,
      "indice_repetition_2" => nil,
      "libelle_commune" => "MAUGUIO",
      "siret" => "48944519700036",
      "id" => 70725092,
      "distribution_speciale" => nil,
      "indice_repetition" => nil,
      "siren" => "489445197",
      "complement_adresse" => nil,
      "unite_legale" => %{
        "statut_diffusion" => "O",
        "nic_siege" => "00036",
        "prenom_usuel" => nil,
        "sigle" => nil,
        "denomination" => "SAFENERGY",
        "id" => 33014385,
        "pseudonyme" => nil,
        "nom_usage" => nil,
        "siren" => "489445197",
        "date_dernier_traitement" => "2019-11-13T15:06:19",
        "annee_effectifs" => nil,
        "categorie_entreprise" => "PME",
        "tranche_effectifs" => nil,
        "identifiant_association" => nil,
        "sexe" => nil,
        "prenom_2" => nil,
        "caractere_employeur" => "N",
        "nom" => nil,
        "created_at" => "2020-07-02T02:56:19.773+02:00",
        "economie_sociale_solidaire" => "N",
        "prenom_4" => nil,
        "date_fin" => nil,
        "date_debut" => "2019-07-01",
        "prenom_3" => nil,
        "date_creation" => "2006-04-01",
        "annee_categorie_entreprise" => "2017",
        "denomination_usuelle_2" => nil,
        "denomination_usuelle_3" => nil,
        "denomination_usuelle_1" => nil,
        ...
      },
      "date_dernier_traitement" => "2019-11-13T15:06:19",
      "annee_effectifs" => nil,
      "denomination_usuelle" => "SAFENERGY",
      "code_pays_etranger" => nil,
      "complement_adresse_2" => nil,
      "tranche_effectifs" => nil,
      "enseigne_1" => nil,
      "numero_voie_2" => nil,
      "geo_id" => "34154_b163",
      "activite_principale_registre_metiers" => nil,
      "geo_l5" => nil,
      "caractere_employeur" => "N",
      "geo_l4" => "MAS DES PERES",
      "nic" => "00036",
      "code_postal" => "34130",
      "libelle_cedex_2" => nil,
      "created_at" => "2020-07-02T03:12:45.814+02:00",
      "numero_voie" => "9002",
      "longitude" => "3.967449",
      "type_voie" => nil,
      "date_debut" => "2019-07-01",
      "code_cedex_2" => nil,
      "date_creation" => "2019-07-01",
      "code_commune_2" => nil,
      "libelle_pays_etranger_2" => nil,
      "libelle_commune_etranger" => nil,
      "latitude" => "43.603798",
      "code_cedex" => nil,
      "geo_score" => "0.95",
      ...
    }
  ],
  "meta" => %{
    "page" => 1,
    "per_page" => 1,
    "total_pages" => 1,
    "total_results" => 1
  }
}

Like вы можете видеть выше (четыре строчки в комментариях), я, например, пытаюсь извлечь элемент «сирена», но это не удалось ... Я ошибаюсь?

Ответы [ 2 ]

2 голосов
/ 10 июля 2020

Используйте Access в целом и Kernel.get_in/2 здесь, в частности

body
|> decode!()
|> get_in(["etablissements", Access.all(), "unite_legale", "siren"])
#⇒ "0"

С помощью Access вы можете фильтровать результат на каждом этапе, получить все ветки, эт c. Здесь мы используем Access.all/0, чтобы добраться до всех элементов списка.

1 голос
/ 10 июля 2020

Думаю, вы хотите перебрать все «этаблисменты» и получить все числа СИРЕНЫ. Вы можете попробовать что-то вроде:

body
|> decode!()
|> Map.get("etablissements")
|> Enum.map(fn etablissement -> Map.get(etablissement, "siren") end)

, предполагая, что структура данных указана выше. Обратите внимание, что Enum.map/2 не связан с модулем Map, но запускает функцию fn etablissement -> Map.get(etablissement, "siren") end для каждой записи списка "etablissements".

Это должно вернуть список со всеми номерами СИРЕНЫ. Если могут быть повторяющиеся записи, вы можете использовать Enum.uniq/1.

...