Elixir phoenix - Render Ecto schema to json with relationships

Image not Found

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

 1  defmodule MyApp.UserView do
 2      use JsonView
 3      def render("user.json", %{user: user}) do
 4      	render_json(user, [:first_name, :last_name, :vatar], [], [])
 5      end
 6  end
 7      
 8  defmodule MyApp.PostView do
 9      use JsonView
10
11      # define which fields return without modifying
12      @fields [:title, :content, :excerpt, :cover]
13      # define which fields that need to format or calculate, you have to define `render_field/2` below
14      @custom_fields [:like_count]
15      # define which view used to render relationship
16      @relationships [author: MyApp.UserView]
17
18      def render("post.json", %{post: post}) do
19          # 1st way if `use JsonView`
20          render_json(post, @fields, @custom_fields, @relationships)
21      end
22
23      def render_field(:like_count, item) do
24          # load like_count from some where
25      end
26  end

And then use it

 1post = %Post{
 2	title: "Hello JsonView",
 3	excerpt: "Now you can render Json easier",
 4	content: "Install and put it to work",
 5	cover: nil,
 6	inserted_at: ~N[2021-07-05 00:00:00],
 7	updated_at: ~N[2021-07-09 00:00:00],
 8	author: %User{
 9		first_name: "Daniel",
10		last_name: "James",
11		email: "[email protected]",
12		avatar: nil,
13		inserted_at: ~N[2021-06-30 00:00:00]
14		updated_at: ~N[2021-07-02 00:00:00]
15	}
16}
17
18MyApp.PostView.render("post.json", %{post: post})
19
20# or invoke from PostController
21render(conn, "post.json", post: post)

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

 1%{
 2	title: "Hello JsonView",
 3	excerpt: "Now you can render Json easier",
 4	content: "Install and put it to work",
 5	cover: nil,
 6  like_count: nil,
 7	author: %{
 8		first_name: "Daniel",
 9		last_name: "James"
10	}
11}

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.