【问题标题】:How to exclude nested model in Ecto Poison encoding如何在 Ecto Poison 编码中排除嵌套模型
【发布时间】:2016-07-11 20:59:31
【问题描述】:

我有一个简单的模型(短版):

defmodule MyApp.User do
  use Ecto.Model

  @derive {Poison.Encoder, only: [:id, :name, :email]}
  schema "users" do
    field :name, :string
    field :email, :string
    belongs_to :company, MyApp.Company

我希望 @derive 在尝试对模型进行编码时排除 :company 关联,但似乎没有。使用 Guardian 序列化程序时会发生这种情况:

defmodule MyApp.GuardianSerializer do
  @behaviour Guardian.Serializer

  alias MyApp.Repo
  alias MyApp.User

  def for_token(user = %User{}), do: { :ok, "User:#{user.id}" }
  def for_token(_), do: { :error, "Unknown resource type" }

  def from_token("User:" <> id), do: { :ok, Repo.get(User, id) }
  def from_token(_), do: { :error, "Unknown resource type" }
end

我实际上并不确定会发生什么

def for_token(user = %User{}), do: { :ok, "User:#{user.id}" }

据我了解,user = %User{} 正在尝试测试作为参数给出的对象是否是有效的 User 变更集,对吗?

但是我得到了这个错误:

无法将关联 :company 从 MyApp.User 编码为 JSON,因为 关联未加载。请确保您已预加载 关联或从要编码的数据中删除

我不想预加载它,因为它需要更多的依赖来编码,这也不起作用,我宁愿忽略它。

为什么@derive 中的only 参数不起作用,我该如何解决这个问题?

【问题讨论】:

  • 如果您执行Poison.encode!(Repo.get(User, 1))(将 1 替换为有效的用户 ID),您是否会收到相同的错误?
  • 我已经更新了问题并添加了一些上下文。是的,如果我尝试直接使用Poison.encode!/1 对其进行编码,也会出现同样的问题
  • 我无法用类似的设置重现这个:Commentbelongs_to Post; Poison.encode!(Repo.get(Comment, 1))@derive {Poison.Encoder, only: [:id, :content]}Comment。您可以尝试在新的最小应用程序中重现该错误吗?
  • 你在预加载关联吗?如果我预加载它,错误将继续与未预加载的 Company 关联...但我不想预加载或编码其中任何一个。
  • 是的,即使这样也能正常工作:Poison.encode! MyApp.Repo.get(MyApp.Comment, 2) |&gt; MyApp.Repo.preload([:post]) 与我在上一条评论中发布的 @derive 相同。

标签: elixir ecto elixir-poison


【解决方案1】:

我终于找到了问题。

我的项目中有一个与旧版本 Ecto 相关的修复,您可以找到关于该 here 的讨论,以及我使用的修复建议 here

所以,基本上我已经在其他地方重新定义了Poison.Encoder,对于所有事情(我知道,这样做很糟糕,而且像往常一样,这是暂时的......)

defimpl Poison.Encoder, for: Any do
  def encode(%{__struct__: _} = struct, options) do
    map = struct
          |> Map.from_struct
          |> sanitize_map
    Poison.Encoder.Map.encode(map, options)
  end

  defp sanitize_map(map) do
    Map.drop(map, [:__meta__, :__struct__])
  end
end

通过删除它,使用最新版本的ecto/poison/phoenix/you-name-it,它可以按预期工作。

非常感谢您的帮助@dogbert

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多