自动为架​​构提供更好的Jason编码器

时间:2018-09-02 12:10:32

标签: json encoding elixir schema phoenix-framework

我收到此警告

警告:Jason.Encoder协议已被合并,Any的实现无效。如果要在编译后或测试期间实施协议,请查看Kernel.defprotocol / 2文档中的“合并”部分       lib / encoder.ex:1

警告:重新定义模块Jason.Encoder.Any(当前版本从/Users/dev/projects/haitracker.com/haitracker-be/_build/dev/lib/jason/ebin/Elixir.Jason.Encoder加载任何光束)       lib / encoder.ex:1

使用以下编码器

defimpl Jason.Encoder, for: Any do
  def encode(%{__struct__: _} = struct, _options) do
    skip_keys =
      case struct.__struct__ do
        Haitracker.User ->
          [
            :local_password_hash,
            :login_status_message
          ]

        # TODO: define skip keys for each model and pass to this function
        _whatever ->
          []
      end

    struct
    |> Map.from_struct()
    |> sanitize_map(skip_keys)
    |> Jason.encode!()
  end

  defp sanitize_map(map, skip_keys) do
    filter = fn {key, val} ->
      cond do
        key in [:__meta__, :__struct__] ->
          false

        is_map(val) ->
          Ecto.assoc_loaded?(val)

        key not in skip_keys ->
          true

        true ->
          false
      end
    end

    map
    |> Enum.filter(filter)
    |> Enum.into(%{})
  end
end

我想知道是否有更好的方法可以仅使用单个编码器配置文件对使用Jason的所有模式进行编码,以便将所有编码选项都定义在一个位置。

1 个答案:

答案 0 :(得分:1)

显然,您不允许任何东西破坏默认的Jason实现。您应该明确告诉Jason如何序列化您的结构。

摘录自Jason README

  

如果您需要对某些未实现协议的结构进行编码,而您拥有该结构,则可以派生实现,指定应将哪些字段编码为JSON:

@derive {Jason.Encoder, only: [....]}
defstruct # ...

也就是说,您应该使用@derive模块属性来明确指定要过滤掉哪些字段。