Предельные поля ответа JSON
Я использую PhoenixFramework и библиотеку Poison. В настоящее время я работаю над REST API. Теперь мне нужно кодировать модель Book
двумя разными способами.
- В списке всех книг только с базовой информацией (
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",
// ...
}
}
Кодировщик 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
Контроллер сниппета
def index(conn, _params) do
books = Repo.all(Book)
json(conn, %{books: books})
end
Как ограничить поля? Я ищу вариант как :only
или же :exclude
, Кто-нибудь сталкивался с этой проблемой?
Спасибо за помощь!
1 ответ
Решение
Вы можете использовать render_many/4 и 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
Обратите внимание, что имя в назначениях (2-й аргумент рендера) определяется модулем. Смотрите пример рендеринга отношения J ко многим ко многим в Phoenix Framework для примера использования другого имени.
Затем вы можете вызвать это с вашего контроллера, используя:
render(conn, "index.json", books: Repo.all(Book))
render(conn, "show.json", book: Repo.get(Book, 1))