这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions registry.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package huma

import (
"encoding"
"encoding/json"
"fmt"
"reflect"
Expand Down Expand Up @@ -92,6 +93,11 @@ func (r *mapRegistry) Schema(t reflect.Type, allowRef bool, hint string) *Schema
// Special case: type provides its own schema
getsRef = false
}
if _, ok := v.(encoding.TextUnmarshaler); ok {
// Special case: type can be unmarshalled from text so will be a `string`
// and doesn't need a ref. This simplifies the schema a little bit.
getsRef = false
}

name := r.namer(origType, hint)

Expand Down
11 changes: 10 additions & 1 deletion schema.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package huma

import (
"encoding"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -686,7 +687,7 @@ func schemaFromType(r Registry, t reflect.Type) *Schema {
return custom
}

// Handle special cases.
// Handle special cases for known stdlib types.
switch t {
case timeType:
return &Schema{Type: TypeString, Nullable: isPointer, Format: "date-time"}
Expand All @@ -700,6 +701,14 @@ func schemaFromType(r Registry, t reflect.Type) *Schema {
return &Schema{}
}

if _, ok := v.(encoding.TextUnmarshaler); ok {
// Special case: types that implement encoding.TextUnmarshaler are able to
// be loaded from plain text, and so should be treated as strings.
// This behavior can be overidden by implementing `huma.SchemaProvider`
// and returning a custom schema.
return &Schema{Type: TypeString, Nullable: isPointer}
}

minZero := 0.0
switch t.Kind() {
case reflect.Bool:
Expand Down
29 changes: 29 additions & 0 deletions schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package huma_test

import (
"bytes"
"encoding"
"encoding/json"
"math/bits"
"net"
Expand Down Expand Up @@ -1172,6 +1173,34 @@ func TestSchemaGenericNamingFromModule(t *testing.T) {
}`, string(b))
}

type MyDate time.Time

func (d *MyDate) UnmarshalText(data []byte) error {
t, err := time.Parse(time.RFC3339, string(data))
if err != nil {
return err
}
*d = MyDate(t)
return nil
}

var _ encoding.TextUnmarshaler = (*MyDate)(nil)

func TestCustomDateType(t *testing.T) {
type O struct {
Date MyDate `json:"date"`
}

var o O
err := json.Unmarshal([]byte(`{"date": "2022-01-01T00:00:00Z"}`), &o)
require.NoError(t, err)
assert.Equal(t, MyDate(time.Date(2022, 1, 1, 0, 0, 0, 0, time.UTC)), o.Date)

r := huma.NewMapRegistry("#/components/schemas/", huma.DefaultSchemaNamer)
s := r.Schema(reflect.TypeOf(o), false, "")
assert.Equal(t, "string", s.Properties["date"].Type)
}

type OmittableNullable[T any] struct {
Sent bool
Null bool
Expand Down