限制 JSON 响应的字段

Limit fields of JSON response

我正在使用 PhoenixFramework 和库 Poison。 目前我正在研究 REST API。现在我需要用两种不同的方式对模型 Book 进行编码。

  1. 在仅包含基础信息的所有图书列表中(GET /books
  2. 在包含所有信息的详细视图中(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 之类的选项。 有人遇到过这个问题吗?

感谢帮助!

您可以使用 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

请注意,assigns 中的名称(render 的第二个参数)由模块决定。有关使用不同名称的示例,请参阅

然后您可以使用以下方法从您的控制器中调用它:

render(conn, "index.json", books: Repo.all(Book))

render(conn, "show.json", book: Repo.get(Book, 1))