模式自定义#
操作模式#
输入/输出体的生成模式可以通过几种方式自定义。首先,在注册操作时,您可以提供自己的请求和/或响应模式,如果您想覆盖整个体。自动生成仅在 OpenAPI 中未提供自己的模式时适用。
code.go
// 使用自定义输入体模式注册操作。
huma.Register(api, huma.Operation{
OperationID: "my-operation",
Method: http.MethodPut,
Path: "/things/{thing-id}",
Summary: "Update a thing",
RequestBody: &huma.RequestBody{
Description: "我的自定义请求模式",
Content: map[string]*huma.MediaType{
"application/json": {
Schema: &huma.Schema{
Type: huma.TypeObject,
Properties: map[string]*huma.Schema{
"foo": {
Type: huma.TypeString,
Extensions: map[string]any{
"x-custom-thing": "abc123",
},
},
},
},
},
},
},
}, func(ctx context.Context, input *MyInput) (*MyOutput, error) {
// 实现代码在此处...
return nil, nil
})
字段模式#
其次,可以按字段基础进行自定义,通过实现一个特殊接口来获取模式,从而允许您例如将额外功能封装在该字段中。这是该接口:
code.go
// SchemaProvider 是一个接口,可以由类型实现,以为其自身提供自定义模式,
// 覆盖内置模式生成。这可用于具有自身特殊序列化规则的自定义类型。
type SchemaProvider interface {
Schema(r huma.Registry) *huma.Schema
}
huma.Registry 会传递给您,并可用于获取嵌入式结构的模式或引用。以下是一个示例,其中我们想要知道字段在作为请求体的一部分发送时是被省略、null 还是值。首先,我们从定义自定义泛型结构开始:
code.go
// OmittableNullable 是一个字段,可以从输入中省略、
// 设置为 `null` 或设置为值。每种状态都会被跟踪,并在处理代码中可检查。
type OmittableNullable[T any] struct {
Sent bool
Null bool
Value T
}
// UnmarshalJSON 从 JSON 输入反序列化此值。
func (o *OmittableNullable[T]) UnmarshalJSON(b []byte) error {
if len(b) > 0 {
o.Sent = true
if bytes.Equal(b, []byte("null")) {
o.Null = true
return nil
}
return json.Unmarshal(b, &o.Value)
}
return nil
}
// Schema 返回表示此值在传输中的模式。
// 它返回包含类型的模式。
func (o OmittableNullable[T]) Schema(r huma.Registry) *huma.Schema {
return r.Schema(reflect.TypeOf(o.Value), true, "")
}
以下是它在操作中的使用方式:
type MyResponse struct {
Body struct {
Message string `json:"message"`
}
}
huma.Register(api, huma.Operation{
OperationID: "omittable",
Method: http.MethodPost,
Path: "/omittable",
Summary: "Omittable / nullable example",
}, func(ctx context.Context, input *struct {
// 将体设置为指针使其可选,因为它可能为 `nil`。
Body *struct {
Name OmittableNullable[string] `json:"name,omitempty" maxLength:"10"`
}
}) (*MyResponse, error) {
resp := &MyResponse{}
if input.Body == nil {
resp.Body.Message = "Body was not sent"
} else if !input.Body.Name.Sent {
resp.Body.Message = "Name was omitted from the request"
} else if input.Body.Name.Null {
resp.Body.Message = "Name was set to null"
} else {
resp.Body.Message = "Name was set to: " + input.Body.Name.Value
}
return resp, nil
})
如果您查看生成的文档,您会看到 name 字段的类型是 string,它是可选的,最大长度为 10,这表明自定义模式正确地用于替换为 OmittableNullable[string] 结构生成的一个。
查看 https://github.com/danielgtaylor/huma/blob/main/examples/omit/main.go 以获取完整示例以及如何调用它。这只是使用字段自定义模式可能性的冰山一角。
深入了解#
- 参考
huma.Schema是一个 JSON Schemahuma.Registry生成并存储 JSON Schemahuma.DefaultSchemaNamer根据类型命名模式
- 外部链接
- 另请参阅