Josh Bavari's Thoughts

Thoughts on technology and philosophy

Custom JSON Encoding in Phoenix

about a 1 minute read

I recently have been working a lot using Leaflet.js to do some mapping.

In some of my models, I use the lovely Geo package for Elixir point and geospatial usage. I needed to add support for Poison to encode my model.

I’ve been serving geo json from my models, and I needed a way to use the JSON encoding way easier. I’m sending some data out to a ZeroMQ socket so I need to encode it by transorming my Geo module in a way that I could encode it with Geo JSON.

I modified my model in two ways – one by putting the @derive directive to tell Poison to encode only certain fields. That is one way.

In another way, I needed to encode it everytime by calling the Geo.JSON.encode method without me having to do it. You can see that in the defimpl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
defmodule MyApp.Point do
  use MyApp.Web, :model

  # Option 1 - specify exactly which fields to encode
  @derive {Poison.Encoder, only: [:id, :name, :geo_json]}
  schema "points" do
    field :name, :string
    field :position, Geo.Point
    field :geo_json, :string, virtual: true

    timestamps
  end

  def encode_model(point) do
    %MyApp.Point{point | geo_json: Geo.JSON.encode(point.position) }
  end

  defimpl Poison.Encoder, for: MyApp.Point do
    def encode(point, options) do
      point = MyApp.Point.encode_model(point)
      Poison.Encoder.Map.encode(Map.take(point, [:id, :name, :geo_json]), options)
    end
  end
end

Cheers.

Comments