JSON API response to Structs using Ecto Schema

Hi @jeromedoyle,

If you want to use Ecto rather than Poison’s protocols, here is an example.

I’m just casting the API response but you could also add Changeset validations if you want and only returning if valid? == true. Hope this helps!

defmodule MyApp.SmartyUSStreet.Response do
  use Ecto.Schema

  alias MyApp.Addresses.Address

  import Ecto.Changeset

  @primary_key false
  embedded_schema do
    field :input_id
    field :input_index, :integer
    field :candidate_index, :integer
    field :addressee
    field :delivery_line_1
    field :delivery_line_2
    field :last_line
    field :delivery_point_barcode

    embeds_one :components, Components do
      field :street_name
      field :city_name
      field :default_city_name
      field :state_abbreviation
      field :zipcode
      field :plus4_code
      # ...
    end

    embeds_one :metadata, Metadata do
      field :record_type
      field :zip_type
      field :county_fips
      field :county_name
      # ...
    end

    embeds_one :analysis, Analysis do
      field :dpv_match_code
      field :dpv_footnotes
      field :dpv_cmra
      # ...
    end
  end

  def list_from_json(data) when is_binary(data) do
    Poison.decode!(data) |> list_from_json()
  end

  def list_from_json(data) when is_list(data) do
    data
    |> Enum.map(fn x -> list_from_json(x) end)
    |> List.flatten()
  end

  def list_from_json(data) when is_map(data) do
    %__MODULE__{}
    |> cast(data, castable_fields(__MODULE__))
    |> cast_embed(:components, with: &embedded_changeset/2)
    |> cast_embed(:metadata, with: &embedded_changeset/2)
    |> cast_embed(:analysis, with: &embedded_changeset/2)
    |> apply_changes()
    |> List.wrap()
  end

  def castable_fields(schema_module) do
    schema_module.__schema__(:fields) -- (schema_module.__schema__(:embeds) ++ schema_module.__schema__(:associations))
  end

  def embedded_changeset(struct, data) do
    struct |> Ecto.Changeset.cast(data, castable_fields(struct.__struct__))
  end
end