Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bluzky/json_view
Elixir library to render Json with relationship
https://github.com/bluzky/json_view
elixir elixir-phoenix json-serializer json-view phoenix-elixir
Last synced: about 23 hours ago
JSON representation
Elixir library to render Json with relationship
- Host: GitHub
- URL: https://github.com/bluzky/json_view
- Owner: bluzky
- License: mit
- Created: 2021-07-10T08:26:41.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2022-04-19T09:02:45.000Z (over 2 years ago)
- Last Synced: 2024-10-30T16:56:11.217Z (15 days ago)
- Topics: elixir, elixir-phoenix, json-serializer, json-view, phoenix-elixir
- Language: Elixir
- Homepage:
- Size: 17.6 KB
- Stars: 30
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# 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`:```elixir
def deps do
[
{:json_view, "~> 0.2.0"}
]
end
```Documentation can be found at [https://hexdocs.pm/json_view](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:
- Keep the original value
- Return value in a new format, or return some calculated data
- Render relationships that defined by Ecto schemaJsonView 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:```elixir
def view do
quote do
...
use JsonView
...
end
end
```Or you can use it directly on your view
```elixir
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)
enddef render_field(:like_count, item) do
# load like_count from some where
end
end
```And then use it
```elixir
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: "[email protected]",
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
```elixir
%{
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
- **Custom field**
```elixir
@custom_fields [:like_count]
# this invokes `render(:like_count, post)`
@custom_fields [like_count: &my_function/1]
# this invokes `my_function.(post)`
```- **Relationship**
```elixir
@relationships [author: MyApp.UserView]
# this invokes `MyApp.UserView.render("user.json", %{user: user})`
@relationships [author: {MyApp.UserView, "basic_profile.json"}]
# this invokes `MyApp.UserView.render("basic_profile.json", %{user: user})`
```## 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`
```elixir
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:
```elixir
use JsonView, after_render: &convert_all_datetime_to_local/1def 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
```