JsonView

Render json easier with relationship and custom data rendering

Installation

The package can be installed by adding json_view to your list of dependencies in mix.exs:

def deps do
  [
    {:json_view, "~> 0.2.0"}
  ]
end

Documentation can be found at https://hexdocs.pm/json_view.

How to use it

Normally, you query data from database then render to JSON and return to client, and you might want to:

JsonView helps to render json data easier by support relationship and custom render data. Most of the time you may want to add it to your view:

  def view do
    quote do
      ...
      use JsonView
      ...
    end
  end

Or you can use it directly on your view

  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"
    }
}

How to define fields and relationships

Data override

JsonView render fields -> custom_fields -> relationships. If they define same field, then the latter will override the prior

Default fields

You can pass a list of default fields and/or custom_fields as options to use JsonView. These fields then merged to fields and custom_fields before rendering data each time you invoke render_json

  use JsonView, fields: [:id, :updated_at], custom_fields: [inserted_at: &to_local_time/2]

Render hook

You can pass a function to process data after JsonView completes rendering like this:

  use JsonView, after_render: &convert_all_datetime_to_local/1

  def convert_all_datetime_to_local(data) do
    Enum.map(data, fn {k, v} ->
      v =
        case v do
          %NaiveDateTime{} -> to_local_datetime(v)
          _ -> v
        end
      {k, v}
    end)
    |> Enum.into(%{})
  end