mcintyre1994
If I have a struct (with maybe some nested structs), and it has atom keys, what’s the most idiomatic way to get from user input in the form of a JSON request body to that struct? In my day job I use Scala + Play Framework and this is really easy to do, but I think in Elixir I’m getting caught up on the fact that user input → atom is a DoS vector.
So Phoenix presents my JSON body to my controller function in conn.body_params, nicely parsed into a map - with string keys. I can’t parse this to a struct using Kernel.struct because the string keys are ignored - and I can’t convert them to atoms without a potential DoS.
The only thing I can think of that would probably work is converting that map back into JSON, and then decoding it using Poison’s as parameter. But that seems really wasteful because Plug already converted it from JSON → map, then I’m doing map → JSON → struct.
I guess I’m wondering if there’s anything more idiomatic/automated/safe than just doing something like this in the controller:
body_params = conn.body_params
user = %User{
name: body_params["name"],
age: body_params["age"],
occupation: %Occupation{
job_title: body_params["occupation"]["job_title"]
}
}
Which seems quite error prone and tedious particularly where there’s a lot of nesting, JSON lists, etc.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #ai
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #elixirconf-eu
- #metaprogramming
- #hex










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
kokolegorille
Converting data from the outside is usually done with changesets in Elixir, with or without database.
Something like
sztosz
Structs are actually just maps with a additional key
__struct__, so%User{a: 1}is simply a map%{__struct__: User, a: 1}underneath. You can hack the map you have, by converting keys from strings to atoms, and then adding the proper__struct__key.Or maybe just simply use
structfunction, here are examples: Kernel — Elixir v1.20.2 but you will have to convert keys from that map to atoms, and then that map to keyword list.From my experience, it’s just easier and more readable, when you have specialized functions in your module that declares that struct. and invoke them whenever you have need to create that struct from params map, You can add there proper validation etc with Ecto embeded schemas etc.
mcintyre1994
Thanks - I had left Ecto out when I started the Phoenix app because I’m not using a database but it looks like changeset is still the best approach here.
daskycodes
If you are still thinking about going completely without ecto you could try something like this
kokolegorille
Hello and welcome,
This could lead to potential :atom overflow,
daskycodes
Hello and thank you,
Thank you for mentioning :atom overflow I haven’t thought about that. Atoms are not garbage-collected.
ityonemo
I think half the elixir community is waiting for the ecto team to break off changesets like Phoenix did with pubsub.
kokolegorille
Spliting ecto and ecto_sql was already nice
fxn
Nice thing about changesets is that you can still define an embedded schema and get casts and validations.
LostKobrakai
One doesn’t even need schemas. There are schemaless changesets.