How to type cast decode JSON as if it came from th

2019-04-08 20:34发布

问题:

When loading date/time types from the database, Ecto will cast to a Ecto.DateTime type. How can the same type casting be applied when loading a model from a JSON string

defmodule Rocket.User do
  use Rocket.Model

  schema "users" do
    field :created_at, :datetime
    field :name, :string
    field :email, :string
    field :password, :string
    field :timezone, :string
  end
end

iex(40)> Poison.decode!(~s({"created_at":"2015-01-21T06:05:10.891Z"}), as: Rocket.User)  
%Rocket.User{created_at: "2015-01-21T06:05:10.891Z", email: nil, id: nil,
 name: nil, password: nil, timezone: nil}

回答1:

If you are using Ecto 0.6.0, the best way is to use changesets:

Ecto.Changeset.cast Poison.decode!(data), %Rocket.User{},
                    ~w(required_fields), ~w(optional_fields)

Using changeset is actually recommended if you are receiving this as external data since you need to cast, filter and validate this data before adding it to the model. You can find more information about them in the Ecto introduction and also in the Ecto.Changeset module documentation.

There is one issue left though: Ecto does not know how to cast the string to datetime. You can however teach it how to by using custom types. I have created a template below, you just need to implement the casting function:

https://gist.github.com/josevalim/1ed574b388c32f056da1

Then in your schema:

timestamps type: Rocket.DateTime

You can find more information in Ecto.Type docs. I am aware we need to improve this in Ecto, I think we should at least be able to parse datetimes in the format specified in JSON.



标签: elixir ecto