Skip to content

Add support for patternProperties #1102

Description

@superstas

Hey @danielgtaylor @wolveix

Thanks for maintaining Huma.

It would be nice to support patternProperties at some point.

For example

type PatternValues map[string]any

func (v PatternValues) Schema(r huma.Registry) *huma.Schema {
	strMin, strMax := 3, 8
	intMin, intMax := 1.0, 100.0

	return &huma.Schema{
		Type: huma.TypeObject,
		PatternProperties: map[string]*huma.Schema{
			"^str_[a-z]{3,8}$": {
				Type:      huma.TypeString,
				MinLength: &strMin,
				MaxLength: &strMax,
				Enum:      []any{"alpha", "bravo", "charlie"},
			},
			"^count_[0-9]{2}$": {
				Type:    huma.TypeInteger,
				Minimum: &intMin,
				Maximum: &intMax,
			},
		},
		AdditionalProperties: false,
	}
}

var _ huma.SchemaProvider = PatternValues{}

type PatternInput struct {
	Body struct {
		Values PatternValues `json:"values"`
	}
}

would have the following OAS

...
    PatternInputBody:
      additionalProperties: false
      properties:
        $schema:
          description: A URL to the JSON Schema for this object.
          examples:
            - https://example.com/schemas/PatternInputBody.json
          format: uri
          readOnly: true
          type: string
        values:
          additionalProperties: false
          patternProperties:
            ^count_[0-9]{2}$:
              maximum: 100
              minimum: 1
              type: integer
            ^str_[a-z]{3,8}$:
              enum:
                - alpha
                - bravo
                - charlie
              maxLength: 8
              minLength: 3
              type: string
          type: object
      required:
        - values
      type: object
...

Validation results

Request body Expected validation Failure reason
{"values":{"str_name":"alpha","count_01":42}} true
{"values":{"count_01":"not an integer"}} false count_01 matches ^count_[0-9]{2}$, but value is not an integer
{"values":{"str_bad":"zo"}} false str_bad matches ^str_[a-z]{3,8}$, but value length is less than 3
{"values":{"str_name":"delta"}} false str_name matches ^str_[a-z]{3,8}$, but value is not in enum alpha, bravo, charlie
{"values":{"count_99":101}} false count_99 matches ^count_[0-9]{2}$, but value is greater than 100
{"values":{"name":"alice"}} false name does not match any allowed pattern and additionalProperties is false

Questions

  • What do you think about supporting it?
  • Would you be open to a PR for it? I have a local prototype, but I’d like to align on the scope first.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions