Using custom type in embedded schema

I am writing an API integration that uses embedded schemas to cast response data before it is used internally. The id fields in the responses are typically integers, and I would like them to convert them to strings.

I could transform these values manually, but there are a number of different responses and schemas, all with the same id format, so I am thinking it could be nice to define a custom type that handles this conversion “behind the scenes”.

I have defined my type as:

defmodule Types.ResponseID do
  @behaviour Ecto.Type
 
  def type, do: :string

  def cast(integer) when is_integer(integer) do
    { :ok, Integer.to_string(integer) }
  end

  def cast(string) when is_binary(string), do: { :ok, string }

  def cast(_), do: :error
end

And my schema:

defmodule Thing do
  use Ecto.Schema

  import Ecto.Changeset

  @primary_key false

  embedded_schema do
    field :id, Types.ResponseID
  end

  def from_response(data) do
    %__MODULE__{}
    |> Ecto.Changeset.cast(data, [:id])
    |> apply_changes()
  end

Which then throws these warnings:

warning: function dump/1 required by behaviour Ecto.Type is not implemented (in module ResponseID)
  lib/types/response_id.ex:1: ResponseID (module)

warning: function embed_as/1 required by behaviour Ecto.Type is not implemented (in module ResponseID)
  lib/types/response_id.ex:1: ResponseID (module)

warning: function equal?/2 required by behaviour Ecto.Type is not implemented (in module ResponseID)
  lib/types/response_id.ex:1: ResponseID (module)

warning: function load/1 required by behaviour Ecto.Type is not implemented (in module ResponseID)
  lib/types/response_id.ex:1: ResponseID (module)

My question - Do I need to add @behaviour Ecto.Type for a custom type in an embedded schema? Or is this a better way to define a custom type for this use case?

I found this comment suggesting that the additional behaviors (e.g. load/dump) are not necessary for custom types in embedded schemas, but I haven’t found any documentation showing an example of how to implement:

Thanks!