edmundobiglia

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

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

Where Next?

Popular in Questions Top

Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
Phillipp
Hey, I have a NanoPi-M3 and try to install Elixir on their Ubuntu image. I followed the Raspberry Pi installation instructions from the ...
New
mathew4509
I have a list say x = ["23gh", "56kh", "97mh"] I would like to pass each element to Val in each iteration. Say, in iteration 1 -------...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
Mooodi
Given a string, how can I get access to its character by index? Enum.at("my_string", 2) doesn't work. Or rather, not char, but a substr...
New
jc00ke
Expanding on this topic: https://forum.elixirforum.net/t/map-typespec-question/19217 Let’s say I have a map with required and optional k...
New

Other popular topics Top

chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30048 115
New
yurko
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New

We're in Beta

About us Mission Statement