Jason encode le binaire en UUID dans Elixir

Sep 22 2020

J'essaie de penser à un moyen propre de remplacer le Jason Encoder pour le binaire qui me permettrait de retirer les UUID du binaire. Voici ce que j'aimerais faire en théorie:

defimpl Jason.Encoder, for: BitString do
  def encode(binary, opts) when is_binary(binary) do
    with false <- String.valid?(binary),
    {:ok, uid} <- Ecto.UUID.cast(binary) do
      uid
    else
    _ -> Jason.Encode.string(binary, opts)
    end
  end

  def encode(bitstring, _opts) do
    raise Protocol.UndefinedError,
      protocol: @protocol,
      value: bitstring,
      description: "cannot encode a bitstring to JSON"
  end
end

Je pense dans le sens de cet exemple de stackoverflow, sauf que je pense que le problème ici est que les types natifs comme BitString ne peuvent pas être écrasés.

Réponses

4 AdamMillerchip Sep 22 2020 at 16:30

Plutôt que d'essayer de remplacer globalement le protocole pour BitString, vous pouvez encapsuler un UUID dans sa propre structure et implémenter le Jason.Encoderprotocole pour cette structure:

defmodule JsonUUID do
  defstruct [:uuid]

  defimpl Jason.Encoder do
    def encode(%JsonUUID{uuid: uuid}, opts) when is_binary(uuid) do
      uuid
      |> Ecto.UUID.cast!()
      |> Jason.Encode.string(opts)
    end
  end
end

Tester:

Jason.encode!(%JsonUUID{uuid: Ecto.UUID.bingenerate()})
=> "\"8cbf3df9-8408-4ce3-ac44-980a0f7dc19b\""