jsonschema: unexport ForType (#71)

There's no evidence that it's needed.

Also, improve doc and error messages.
This commit is contained in:
Jonathan Amsterdam 2025-06-30 14:44:40 -04:00 • committed by GitHub
commit 2facfc6ffe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 25 additions and 26 deletions

View file

@ -40,7 +40,7 @@ or as a value of this type:
# Inference
The [For] and [ForType] functions return a [Schema] describing the given Go type.
The [For] function returns a [Schema] describing the given Go type.
The type cannot contain any function or channel types, and any map types must have a string key.
For example, calling For on the above Player type results in this schema:

View file

@ -15,40 +15,39 @@ import (
// For constructs a JSON schema object for the given type argument.
//
// It is a convenience for ForType.
func For[T any]() (*Schema, error) {
return ForType(reflect.TypeFor[T]())
}
// ForType constructs a JSON schema object for the given type.
// It translates Go types into compatible JSON schema types, as follows:
// - strings have schema type "string"
// - bools have schema type "boolean"
// - signed and unsigned integer types have schema type "integer"
// - floating point types have schema type "number"
// - slices and arrays have schema type "array", and a corresponding schema
// for items
// - maps with string key have schema type "object", and corresponding
// schema for additionalProperties
// - structs have schema type "object", and disallow additionalProperties.
// - Strings have schema type "string".
// - Bools have schema type "boolean".
// - Signed and unsigned integer types have schema type "integer".
// - Floating point types have schema type "number".
// - Slices and arrays have schema type "array", and a corresponding schema
// for items.
// - Maps with string key have schema type "object", and corresponding
// schema for additionalProperties.
// - Structs have schema type "object", and disallow additionalProperties.
// Their properties are derived from exported struct fields, using the
// struct field json name. Fields that are marked "omitempty" are
// struct field JSON name. Fields that are marked "omitempty" are
// considered optional; all other fields become required properties.
//
// It returns an error if t contains (possibly recursively) any of the following Go
// For returns an error if t contains (possibly recursively) any of the following Go
// types, as they are incompatible with the JSON schema spec.
// - maps with key other than 'string'
// - function types
// - complex numbers
// - unsafe pointers
//
// The cannot be any cycles in the types.
// TODO(rfindley): we could perhaps just skip these incompatible fields.
func ForType(t reflect.Type) (*Schema, error) {
return typeSchema(t)
// The types must not have cycles.
func For[T any]() (*Schema, error) {
// TODO: consider skipping incompatible fields, instead of failing.
s, err := forType(reflect.TypeFor[T]())
if err != nil {
var z T
return nil, fmt.Errorf("For[%T](): %w", z, err)
}
return s, nil
}
func typeSchema(t reflect.Type) (*Schema, error) {
func forType(t reflect.Type) (*Schema, error) {
// Follow pointers: the schema for *T is almost the same as for T, except that
// an explicit JSON "null" is allowed for the pointer.
allowNull := false
@ -82,14 +81,14 @@ func typeSchema(t reflect.Type) (*Schema, error) {
return nil, fmt.Errorf("unsupported map key type %v", t.Key().Kind())
}
s.Type = "object"
s.AdditionalProperties, err = typeSchema(t.Elem())
s.AdditionalProperties, err = forType(t.Elem())
if err != nil {
return nil, fmt.Errorf("computing map value schema: %v", err)
}
case reflect.Slice, reflect.Array:
s.Type = "array"
s.Items, err = typeSchema(t.Elem())
s.Items, err = forType(t.Elem())
if err != nil {
return nil, fmt.Errorf("computing element schema: %v", err)
}
@ -115,7 +114,7 @@ func typeSchema(t reflect.Type) (*Schema, error) {
if s.Properties == nil {
s.Properties = make(map[string]*Schema)
}
s.Properties[info.Name], err = typeSchema(field.Type)
s.Properties[info.Name], err = forType(field.Type)
if err != nil {
return nil, err
}