Why does the api generated via phx.gen.json expect the name of resource to be passed in the json object?

Working with other frameworks, to insert data, I would send a POST request to the resource endpoint /api/users with the following payload:

{"email": "something@awesome.com", "username": "something_awesome"}

However, phoenix expects this to be in the json body:

{"user": {"email": "something@awesome.com", "username": "something_awesome"}}

This threw a wrench in the cogs of my django-rest-framework trained brain.
So why do we do it this way in phoenix universe?

1 Like

That’s just the generator, not specifically how everybody does it. Do what makes you happy :relaxed:

1 Like

I think two reasons:

  • JSON hijacking: it seems this attack is no longer valid, but the argument was that instead of returning an array of users, you’d do {"users": [...]}; for consistency, you’d do {"user": {...}} too and that leads to using that same shape in the request,
  • Extensibility: APIs often allow preloading other entities in the same request, for example load the account details with the user {"user": {...}, "account": {...}}; you could do a similar thing for the requests.

But as @cmo pointed out - you can do whatever works for you.

1 Like

Phoenix also does the same scoping for forms so doing it with json endpoints will make switching from one to the other easier as well. This makes it easier for beginners in the framework, which those generators cater to the most.

1 Like

Is there a blog post or something which could take me to the other way?
I would like to try to replace a django backend with phoenix for a few of my applications without touching the frontend.

You can remove the pattern match %{"thing" => thing} = params in your controller functions and just replace it with %{} = thing if you want to not have it scoped to a field in the map.

1 Like