How to apply json_write_schema in NewType to open_api schema model

hello. I’m a beginner who has just studied elixir and ash.

I wanted to add the maxLength, minLength, and pattern properties in the Openapi Model type through Ash constructs

When I checked the code, I think I can add it through json_write_schema.

 use Ash.Type.NewType,
      subtype_of: :string

    use AshJsonApi.Type

    @base_scehma %{
      "type" => "string"
    }

    @impl AshJsonApi.Type
    def json_write_schema(constraints) do
      @base_scehma
      |> apply_min_length(Keyword.get(constraints, :min_length))
      |> apply_max_length(Keyword.get(constraints, :max_length))
      |> apply_pattern(Keyword.get(constraints, :match))
    end

I implemented it in this way and adds to /json_schema is well reflected.
/open_api is not reflected, so I checked the code

/ash_json_api/json_schema/json_schema.ex

 defp resource_write_attribute_type(%{type: type} = attr, action_type) do
    if embedded?(type) do
      embedded_type_input(attr, action_type)
    else
      if :erlang.function_exported(type, :json_write_schema, 1) do
        type.json_write_schema(attr.constraints)
      else
        resource_attribute_type(attr)
      end
    end
  end

/ash_json_api/json_schema/open_api.ex

    def resource_write_attribute_type(%{type: type} = attr, resource, action_type, format) do
      cond do
        Ash.Type.NewType.new_type?(type) ->
          new_constraints = Ash.Type.NewType.constraints(type, attr.constraints)
          new_type = Ash.Type.NewType.subtype_of(type)

          resource_write_attribute_type(
            Map.merge(attr, %{type: Ash.Type.get_type(new_type), constraints: new_constraints}),
            resource,
            action_type,
            format
          )

        AshJsonApi.JsonSchema.embedded?(type) ->
          embedded_type_input(attr, action_type)

        true ->
          if :erlang.function_exported(type, :json_write_schema, 1) do
            type.json_write_schema(attr.constraints)
          else
            resource_attribute_type(attr, resource, format)
          end
      end
      |> with_attribute_description(attr)
    end

If you are written in this way, it is not going to json_write_schema if it is newType.

  def resource_write_attribute_type(%{type: type} = attr, resource, action_type, format) do
      cond do
        :erlang.function_exported(type, :json_write_schema, 1) ->
          type.json_write_schema(attr.constraints)

        Ash.Type.NewType.new_type?(type) ->
          new_constraints = Ash.Type.NewType.constraints(type, attr.constraints)
          new_type = Ash.Type.NewType.subtype_of(type)

          resource_write_attribute_type(
            Map.merge(attr, %{type: Ash.Type.get_type(new_type), constraints: new_constraints}),
            resource,
            action_type,
            format
          )

        AshJsonApi.JsonSchema.embedded?(type) ->
          embedded_type_input(attr, action_type)

        true -> 
           resource_attribute_type(attr, resource, format)
      end
      |> with_attribute_description(attr)
    end

Shouldn’t it be modified like the code above? Or are I approaching in the wrong way?

I didn’t speak English and translated it. The article may be awkward

Yes, you are correct. We should have a check for function_exported(type, :json_write_schema, 1) at the beginning of that cond statement. Great find! Would you like to PR that change?

1 Like

Sure, I’ll open a PR for that. thanks!

1 Like