Reputation: 1514
I'm using the PhoenixFramework and the library Poison.
Current I'm working on an REST API. Now I need to encode the model Book
in two different ways.
GET /books
)GET /book/1
)GET /books
{
"books": [
{
"id": 1,
"name": "Book one"
},
{
"id": 2,
"name": "Book two"
},
// ...
]
}
GET /books/1
{
"book": {
"id": 1,
"name": "Book one",
"description": "This is book one.",
"author": "Max Mustermann",
// ...
}
}
Encoder of Book
defimpl Poison.Encoder, for: MyProject.Book do
@attributes [:id, :name, :description, :author]
def encode(project, _options) do
project
|> Map.take(@attributes)
|> Poison.encode!
end
end
Snippet controller
def index(conn, _params) do
books = Repo.all(Book)
json(conn, %{books: books})
end
How to limit the fields? I search for a option like :only
or :exclude
.
Has anyone experience with this problem?
Thanks for help!
Upvotes: 2
Views: 525
Reputation: 84180
You can use render_many/4 and render_one/4:
defmodule MyApp.BookView do
def render("index.json", %{books: books}) do
render_many(books, __MODULE__, "book.json")
end
def render("show.json", %{book: book}) do
render_one(book, __MODULE__, "full_book.json")
end
def render("book.json", %{book: book}) do
%{
id: book.id,
name: book.name
}
end
def render("full_book.json", %{book: book}) do
%{
id: book.id,
name: book.name,
description: description,
author: book.author
...
}
end
end
Please note that the name in assigns (2nd argument of render) is determined by the module. See Render many to many relationship JSON in Phoenix Framework for an example of using a different name.
You can then call this from your controller using:
render(conn, "index.json", books: Repo.all(Book))
render(conn, "show.json", book: Repo.get(Book, 1))
Upvotes: 5