0

I made a get request with HTTPoison, but now I'm trying to parse the JSON file. For that I'm using Poison library. But I'm having some problems to get an element from the JSON object.

Here my code :

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

My output:

%{
  "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 you can see above (four lines in comments), I'm trying to extract "siren" element for instance but it failed... Am I off the mark ?

2 Answers2

2

Use Access in general and Kernel.get_in/2 here in particular

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

With Access you might filter the outcome on each step, get all branches, etc. Here we use Access.all/0 to get to all elements of the list.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • Thanks Aleksei Matiushkin, it works again! Kernel.get_in/2 is the fonction of the situation you're right! But to get "siren" we don't need to filter "unit_legal" branch, do we ? This is a "siren" value before no ? Is it to avoid getting both ? And if I don't precise your path but this : _["etablissements", Access.all(), "siren"]_ I need to call Enum.uniq/1 next ? – Guichard Lucas Jul 10 '20 at 12:58
  • siren is presented on both levels, check your data. This is just an example, now you know how to do it, so you can get whatever you want. – Aleksei Matiushkin Jul 10 '20 at 13:00
1

I guess you want to iterate over all "etablissements" and retrieve all SIREN numbers. You can try something like:

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

assuming the data structure is the one shown above. Notice that Enum.map/2 is not related to the Map module, but runs the function fn etablissement -> Map.get(etablissement, "siren") end on each entry of the "etablissements" list.

This should return a list with all SIREN numbers. If there might be duplicate entries, you can use Enum.uniq/1.

Tangui
  • 3,626
  • 2
  • 26
  • 28