问题
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.
来源:https://stackoverflow.com/questions/28060690/how-to-type-cast-decode-json-as-if-it-came-from-the-database