Jason 在 Elixir 中将二进制编码为 UUID

Jason encode binary to UUID in Elixir

我正在尝试想出一种干净的方法来覆盖二进制文件的 JasonEncoder,这样我就可以从二进制文件中提取 UUID。这是我理论上想做的事情:

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

我按照 Whosebug 示例的思路思考,但我认为这里的问题是不能覆盖像 BitString 这样的原生类型。

与其尝试全局覆盖 BitString 的协议,不如将 UUID 包装在其自己的结构中,并为该结构实施 Jason.Encoder 协议:

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

测试:

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