【问题标题】:Poison.Encoder how to rename properties in rendered JSON?Poison.Encoder 如何在呈现的 JSON 中重命名属性?
【发布时间】:2015-11-17 12:09:03
【问题描述】:

我有下面的 Ecto 型号。渲染时,我希望 JSON 将属性名称“layers”替换为“tilemap_layers”。

我的应用程序中有许多类型的“层”,所以当我创建我的数据库模式时,我需要创建一个唯一命名的模式。但是,此 JSON 将由第三方客户端使用,必须将其命名为“层”。

推荐的方法是什么?

模型在这里:

defmodule MyProject.Tilemap do
  use MyProject.Web, :model

  @derive {Poison.Encoder, only: [
    :name,
    :tile_width,
    :tile_height,
    :width,
    :height,
    :orientation,
    :tilemap_layers,
    :tilesets
  ]}

  schema "tilemaps" do

    field :name, :string
    field :tile_width, :integer
    field :tile_height, :integer
    field :width, :integer
    field :height, :integer
    field :orientation, :string

    has_many :tilemap_layers, MyProject.TilemapLayer
    has_many :tilesets, MyProject.Tileset

    timestamps
  end

  @required_fields ~w(tile_width tile_height width height)
  @optional_fields ~w()

  @doc """
  Creates a changeset based on the `model` and `params`.

  If no params are provided, an invalid changeset is returned
  with no validation performed.
  """
  def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
  end
end

【问题讨论】:

    标签: json elixir phoenix-framework ecto


    【解决方案1】:

    Poison 在使用@deriving 时不提供别名方式

    您可以:

    使用defimpl(取自the docs)自行指定实现:

    defimpl Poison.Encoder, for: Person do
      def encode(%{name: name, age: age}, _options) do
        Poison.Encoder.BitString.encode("#{name} (#{age})")
      end
    end
    

    重命名架构中的字段:

    has_many :layers, MyProject.TilemapLayer

    或使用 Phoenix View:

    defmodule MyProject.TilemapView do
      use MyProject.Web, :view
    
      def render("index.json", %{tilemaps: timemaps}) do
        render_many(tilemaps, __MODULE__, "tilemap.json")
      end
    
      def render("tilemap.json", %{tilemap: tilemap}) do
        %{
          name: tilemap.name,
          ...
          layers: render_many(layers, MyProject.TilemapLayerView, "tilemap_layer.json")
        }
      end
    end
    

    然后创建一个TilemapLayerView:

    defmodule MyProject.TilemapLayerView do
      use MyProject.Web, :view
    
      def render("tilemap_layer.json", %{tilemap_layer: tilemap_layer}) do
        %{
          name: timemap_layer.name
        }
      end
    end
    

    【讨论】:

    • 再次感谢 Gazler!我正在尝试 foreign_key 选项,因为这是我真正想要的
    • 哇!这行得通!我确实需要更改一个小错字。我改变了 foreign_key: :tilemap_id
    • @JoshPetitt 您实际上可能不需要指定foreign_key。你可以不试试吗?
    • 顺便说一句,这通过更改foreign_key对我有用,所以我编辑了你的答案。如果这是错误的,请改回来:-)
    • Gazler,你又是对的!我不需要foreign_key,我已经删除了它,它仍然可以按我的意愿工作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-03
    • 2016-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多