Phoenix app with both html and json end point


My phoenix app currently supports server side rendering. I would like it to support json end point as well. I know I can easily do this in router.ex by adding a scope: β€œ/api/” and pipe_through api plug. However I do not know if I should create seperate controllers for the json app or I should modify existing controllers and render different view depending on the request. Any convention or thoughts related to this? Thanks!


From my experience, the same controllers returning JSON view only works when the app is really simple CRUD-type of thing.

The needs of API client (either JS or mobile) are usually more specific, and you may want to optimize how and what data is being sent to those clients. This could result in messy controller code.

Go with the same controllers only when the API and pages you show match really well, and the thing is really simple.

If in doubt - build separate controllers. This does not hurt that much, sometimes more code is better than less - but convoluted code.


Hey there!

In my opinion, you should definitely create separate controllers for your API pipeline. As you’ve already said, setup your router to scope on /api or similar and pipe_through :api, where your api pipeline consists of at least plug :accepts, ["json"]

The alternative would be to pattern match on conn in a single controller and either render HTML or JSON views depending on the format request header or something. To me, this mixes concerns a bit too much and makes your pipelines much less flexible.


Thanks for the input guys!

1 Like

You don’t need to pattern match in the controller. Phoenix already handles different views based on what the browser requests. For example when I do render(conn, :request, blah_args: blah_args) then it will render my "index.html" template called via render if html is requested, or it will call my render function that is matched on "index.json" for the JSON conversion (I also have others too). :slight_smile: