hariharasudhan94
How to get struct from map - elixir?
Lets say I have map like this fetching from my database
%{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => "XXXX@gmail.com", "name" => "Hariharasudhan", "password_hash" => "XXXX", "phone" => "XXXX"}
and i have struct like follow
> @primary_key{:id, :binary_id, autogenerate: true}
schema "users" do
field :name, :string
field :email, :string
field :phone, :string
field :password_hash, :string
end'
What is best way to convert Map to User Struct?
note:
I need to do this convertion on each request after authentication , so I need effective way to achieve this?
Marked As Solved
hubertlepicki
Also Liked
manukall
Nicd
This is dangerous as it doesn’t check that the keys in map_defaults actually correspond to keys of the struct. You may end up with a broken struct which is annoying to debug. What you should do is:
s = struct!(User, map_defaults)
This will ensure that keys that are in @enforce_keys must be exist and there are no keys that don’t exist in the struct. Otherwise it will raise an error. There is also Kernel.struct/2 (i.e. without exlamation mark) that will just discard unknown keys and won’t enforce @enforce_keys.
mbuhot
Untested, but it seems like cast and apply_changes should do what you want:
%User{} |> Ecto.Changeset.cast(map, User.__schema__(:fields)) |> Ecto.Changeset.apply_changes()
Last Post!
dubeypranav4
I think this approach is the right fit for me. It preserves Ecto’s type casting without relying on validations that feel out of place when loading from the DB. A changeset makes sense in the app-to-DB direction, but going the other way it’s redundant since the data has already passed validation (at least if Ecto is the only DB writer — otherwise falling back to a proper changeset is fine).
pry(2)>
Ecto.Changeset.cast(struct(schema_module), params, schema_module.__schema__(:fields))
|> Ecto.Changeset.apply_changes()
%Mozek.V3.Orchestrator.Rule.Instance.RequestSchema{
__meta__: #Ecto.Schema.Metadata<:built, "v3_rule_instance_requests">,
id: 207,
freshness_stat_id: 718,
inserted_at: ~U[2025-08-22 11:34:45Z]
}
A utility function like this works well — it handles type casting and embeds (associations could be added similarly if needed):
@spec cast_to_struct(module(), map()) :: struct()
def cast_to_struct(schema_module, params) when is_atom(schema_module) and is_map(params) do
unless has_changeset?(schema_module) do
raise "Schema #{inspect(schema_module)} does not have a changeset/2 function"
end
fields = schema_module.__schema__(:fields) -- schema_module.__schema__(:embeds)
struct(schema_module)
|> Ecto.Changeset.cast(params, fields)
|> then(fn cs ->
Enum.reduce(schema_module.__schema__(:embeds), cs, fn embed, acc ->
Ecto.Changeset.cast_embed(acc, embed)
end)
end)
|> Ecto.Changeset.apply_changes()
end
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









