DEV Community

Cover image for Elixir phoenix - Render Ecto schema to json with relationships
Dung Nguyen for OnPoint Vietnam

Posted on • Edited on

4

Elixir phoenix - Render Ecto schema to json with relationships

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
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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"
    }
}
Enter fullscreen mode Exit fullscreen mode

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.

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay