【问题标题】:Poison Encode encoding nested modelsPoison Encode 编码嵌套模型
【发布时间】:2015-10-17 17:02:32
【问题描述】:

喂,

我正在尝试对一些嵌套的 Ecto 模型进行编码,但遇到了问题。我意识到我无法对未加载的模型进行编码,我希望有可能只选择一个结构而不加载其余部分,同时有可能选择整棵树。

我用过defimpl的方法,例子:

defimpl Poison.Encoder, for: Hangman.MasterCat do
    def encode(page, _options) do
      %{
        id: page.id,
        name: page.name,
        categories: page.categories
      } |> Poison.Encoder.encode([])
    end
  end
defimpl Poison.Encoder, for: Hangman.Category do
    def encode(category, _options) do
      IO.inspect(category.words)
      %{
        id: category.id,
        name: category.name,
        words: category.words
      } |> Poison.Encoder.encode([])
    end
  end
defimpl Poison.Encoder, for: Hangman.Word do
    def encode(page, _options) do
      %{
        content: page.content
      } |> Poison.Encoder.encode([])
    end
  end

这适用于整个结构,但不适用于仅选择 MasterCats 并且会出现此类错误。

cannot encode association :categories from Hangman.MasterCat to JSON because the association was not loaded. Please make sure you have preloaded the association or remove it from the data to be encoded

【问题讨论】:

    标签: elixir phoenix-framework ecto


    【解决方案1】:

    您还需要为类别定义相同的编码器,依此类推。其实有一个更简单的方法,如果你使用的是最新的 Poison,你可以这样写:

    defmodule Hangman.MasterCat do
      use Ecto.Model
    
      @derive {Poison.Encoder, only: [:id, :name, :categories]}
      schema "..." do
    

    这样,Elixir 会自动为您实现协议。只要您为您关心的类型派生编码器,您就应该很好。对于复杂的情况,像您一样显式实现协议是可行的方法。

    【讨论】:

    • 我已经这样做了。我的协议有问题,需要我预加载我目前可能不需要的。例如,当我显示主类别列表时,我不想显示他们的孩子。但是当我展示整个结构时(出于某种原因),我需要展示它们。
    • 您可以随时在编码器中预加载,Ecto 不会预加载两次。但我建议您根据需要正确预加载,而不是在编码器中进行。
    • 是的,我想做什么,但我可能又把我的问题写错了。每个型号可以有多个编码器吗?如果没有,我在编码未预加载的值时遇到错误,这是我试图避免的。
    • 如果您希望每个模型有多个编码器,我建议您使用 Phoenix 视图。以mix phoenix.gen.json 为例,查看生成的内容。
    猜你喜欢
    • 1970-01-01
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    • 2023-03-13
    • 2017-07-06
    • 2022-08-22
    • 2018-05-13
    相关资源
    最近更新 更多