edmundobiglia
Custom Jason.Encoder implementation to render NaiveDateTime as DateTime
I’m somewhat new to Elixir. I have a Phoenix project and I need my endpoints to always return DateTime, even when NaiveDateTime fields are passed to render functions on views. I tried to do a custom implementation of Jason.Encoder, but it is not working.
Original implementation (/deps/jason/lib/encoder.ex):
defimpl Jason.Encoder, for: [Date, Time, NaiveDateTime, DateTime] do
def encode(value, _opts) do
[?\", @for.to_iso8601(value), ?\"]
end
end
My implementation (my_project/lib/my_project/custom_encoder.ex)
defimpl Jason.Encoder, for: NaiveDateTime do
def encode(value, _opts) do
value |> DateTime.from_naive!("Etc/UTC") |> DateTime.to_iso8601()
end
end
However, this does nothing. Even if I change the original lib file implementation and recompile, I still get naive datetimes on my endpoints. Could anyone shed some light on how could I achieve this?
Many thanks in advance!
Most Liked
joaoevangelista
Unfortunately an overriding implementation will not work because Elixir does not support overriding protocols. Here is a similar case to yours.
You would need to create a wrapper struct and then create an Jason.Encoder implementation for it. For example:
defmodule MyApp.TzDateTime do
@type t :: %__MODULE__{value: DateTime.t()}
@enforce_keys :value
defstruct value: nil
@spec new(DateTime.t() | NaiveDateTime.t()) :: t()
def new(%DateTime{} = value) do
%__MODULE__{value: value}
end
def new(%NaiveDateTime{} = value) do
%__MODULE__{value: DateTime.from_naive!(value, "Etc/UTC")}
end
defimpl Jason.Encoder do
def encode(%MyApp.TzDateTime{value: value}, _opts), do: DateTime.to_iso8601(value)
end
end
And on your Phoenix view that renders the JSON:
defmodule MyApp.MyStuffView do
use MyApp, :view
def render("index.json", %{mystuffs: mystuffs}) do
%{data: render_many(mystuffs, MyApp.MyStuffView, "mystuff.json")}
end
def render("show.json", %{mystuff: mystuff}) do
%{data: render_one(mystuff, MyApp.MyStuffView, "mystuff.json")}
end
def render("mystuff.json", %{mystuff: mystuff}) do
%{date: MyApp.TzDateTime.new(Mystuff.my_date_field)}
end
end
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








