Search code examples
elixirphoenix-frameworkelixir-poison

Case statement when processing HTTPoison call


I'm trying to use the same HTTPoison calls for an API call that returns either multiple items or a single item. The response for multiple items throws them into an "items" property, while the single item just returns the item info as the JSON string.

Here is my code:

  def process_url(method, id \\ 0) do
    if id > 0 do
      "http://api.call.com/#{method}/#{id}?key=API_KEY"
    else
      "http://api.call.com/#{method}?key=API_KEY"
    end
  end

  def process_response_body(body) do
    body
    |> Poison.decode!(as: %{"items" => [%Item{}]})
    |> Map.fetch!("items")
  end

In process_response_body, how can I have it check for the items property in the JSON response, and if it doesn't exist, process it differently?


Solution

  • I'd just decode the result and write a multi-headed function to pack it into your objects. Something like:

    def process_response_body(body) do
      body
      |> Poison.decode!
      |> unpack
    end
    
    def unpack(%{"items" => items}) do
      Enum.map(items, &struct(Item, &1))
    end
    def unpack(%{"item" => item}), do: struct(Item, item)
    

    Or with a case:

    body
    |> Poison.decode!
    |> case do
      %{"items" => items} -> Enum.map(items, &struct(Item, &1))
      %{"item" => item} -> struct(Item, item)
    end