Can't render JSON with View

I have an endpoint defined in my routes.ex file like this:

  scope "/api", TesteWeb do
    pipe_through :api

    post "/classify", ClassifierController, :classify

In my classifier_controller.ex file I have:

defmodule TesteWeb.ClassifierController do
  use TesteWeb, :controller

  def classify(conn, _params) do
    # I'm testing with hardcoded data...
    request = %{sentence: "Bom dia", model_id: "123"}
    render(conn, "show.json", request: request)


And finally, in my classifier_view.ex file, I have:

defmodule TesteWeb.ClassifierView do
  use TesteWeb, :view

  def render("show.json", %{request: request}) do
    %{response: render_one(request,TesteWeb.ClassifierView, "response.json")}

  def render("response.json", %{request: request}) do
    %{response: "ok", sentece: request.sentence}


When I make a POST request to http://localhost:4000/api/classify, I get the following error:

[error] #PID<0.471.0> running TesteWeb.Endpoint (connection #PID<0.470.0>, stream id 1) terminated
Server: localhost:4000 (http)
Request: POST /api/classify
** (exit) an exception was raised:
** (Phoenix.Template.UndefinedError) Could not render “response.json” for TesteWeb.ClassifierView, please define a matching clause for render/2 or define a template at “lib/teste_web/templates/classifier/*”. No templates were compiled for this module.

Why it can’t render response.json if it is defined in classifier_view.ex?

Hello and welcome,

When You want to debug something like this, You can add a catch all clause and inspect the params… Put this at the end.

  def render(any_string, message) do
    IO.puts any_string
    IO.inspect message

Then You will see why the pattern is not matched :slight_smile:

I think You have a typo here


Thank you very much!!

Your tip worked very well and I’ve figured out the problem.
The render_one(request,TesteWeb.ClassifierView, "response.json") function pass a structure like

  classifier: %{model_id: "123", sentence: "Bom dia"},
  view_module: TesteWeb.ClassifierView,
  view_template: "response.json"

Where the classifier key came from?

Apart from the name You are using, it looks similar to what I do…

defmodule AppApiWeb.UserView do
  use AppApiWeb, :view
  alias AppApiWeb.UserView

  def render("index.json", %{users: users}) do
    %{data: render_many(users, UserView, "user.json")}

  def render("show.json", %{user: user}) do
    %{data: render_one(user, UserView, "user.json")}

  def render("user.json", %{user: user}) do

Try to replace request by classifier and see how it goes. I think under the hood it will match the name of your view.

BTW from the documentation site, You can use as to specify which name to use…

So in your case, that would have been

render_one(request, TesteWeb.ClassifierView, "response.json", as: :request)
1 Like

Great tip!

1 Like