Elixir phoenix — Render Ecto schema to json with relationships

Dzung Nguyen
2 min readJul 31, 2021

When writing API with Phoenix and render json to client,

  • For some fields I want to keep it original value.
  • For some fields, I want to do some calculation or format data before returning.
  • And I want to render Ecto association too.

An while working on an project at OnPoint I have build a little module that helps to do this easier.

I have extract that module and release as a package named JsonView. Its source code is hosted on github:

https://github.com/bluzky/json_view

You can use it with Phoenix.View or use it independently. It helps to manipulate data, and handle rendering association automatically.

I have published an article on how to write it
A better way to render json response in Elixir Phoenix

Let’s take a look.

First define view modules

defmodule MyApp.UserView do
use JsonView
def render("user.json", %{user: user}) do
render_json(user, [:first_name, :last_name, :vatar], [], [])
end
end
defmodule MyApp.PostView do
use JsonView
# define which fields return without modifying
@fields [:title, :content, :excerpt, :cover]
# define which fields that need to format or calculate, you have to define `render_field/2` below
@custom_fields [:like_count]
# define which view used to render relationship
@relationships [author: MyApp.UserView]
def render("post.json", %{post: post}) do
# 1st way if `use JsonView`
render_json(post, @fields, @custom_fields, @relationships)
end
def render_field(:like_count, item) do
# load like_count from some where
end
end

And then use it

post = %Post{
title: "Hello JsonView",
excerpt: "Now you can render Json easier",
content: "Install and put it to work",
cover: nil,
inserted_at: ~N[2021-07-05 00:00:00],
updated_at: ~N[2021-07-09 00:00:00],
author: %User{
first_name: "Daniel",
last_name: "James",
email: "daniel@example.com",
avatar: nil,
inserted_at: ~N[2021-06-30 00:00:00]
updated_at: ~N[2021-07-02 00:00:00]
}
}
MyApp.PostView.render("post.json", %{post: post})# or invoke from PostController
render(conn, "post.json", post: post)

This is the result that you can use to return from PhoenixController

%{
title: "Hello JsonView",
excerpt: "Now you can render Json easier",
content: "Install and put it to work",
cover: nil,
like_count: nil,
author: %{
first_name: "Daniel",
last_name: "James"
}
}

If you have any feedback, please comment or create an issue.

In the next post I will go through step by step to write this library.

--

--

Dzung Nguyen

I'm a full-stack web developer that are so lazy to code to much so I have to learn to do it the smart way.