Jason codifica binario a UUID en Elixir

Sep 22 2020

Estoy tratando de pensar en una manera limpia de anular el codificador Jason para binarios que me permitiría extraer UUID de binarios. Esto es lo que me gustaría hacer en teoría:

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

Estoy pensando en la línea de este ejemplo de stackoverflow, excepto que creo que el problema aquí es que los tipos nativos como BitString no se pueden sobrescribir.

Respuestas

4 AdamMillerchip Sep 22 2020 at 16:30

En lugar de intentar anular globalmente el protocolo BitString, puede envolver un UUID en su propia estructura e implementar el Jason.Encoderprotocolo para esa estructura:

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

Prueba:

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