 Documentation
      ¶
      Documentation
      ¶
    
    
  
    
  
    Overview ¶
Package jsonschema uses reflection to generate JSON Schemas from Go types [1].
If json tags are present on struct fields, they will be used to infer property names and if a property is required (omitempty is present).
[1] http://json-schema.org/latest/json-schema-validation.html
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // TrueSchema defines a schema with a true value TrueSchema = &Schema{boolean: &[]bool{true}[0]} // FalseSchema defines a schema with a false value FalseSchema = &Schema{boolean: &[]bool{false}[0]} )
var Version = "https://json-schema.org/draft/2020-12/schema"
    Version is the JSON Schema version.
Functions ¶
func ExtractGoComments ¶
ExtractGoComments will read all the go files contained in the provided path, including sub-directories, in order to generate a dictionary of comments associated with Types and Fields. The results will be added to the `commentsMap` provided in the parameters and expected to be used for Schema "description" fields.
The `go/parser` library is used to extract all the comments and unfortunately doesn't have a built-in way to determine the fully qualified name of a package. The `base` paremeter, the URL used to import that package, is thus required to be able to match reflected types.
When parsing type comments, we use the `go/doc`'s Synopsis method to extract the first phrase only. Field comments, which tend to be much shorter, will include everything.
func NewProperties ¶ added in v0.9.0
func NewProperties() *orderedmap.OrderedMap[string, *Schema]
NewProperties is a helper method to instantiate a new properties ordered map.
func ToSnakeCase ¶
ToSnakeCase converts the provided string into snake case using dashes. This is useful for Schema IDs and definitions to be coherent with common JSON Schema examples.
Types ¶
type Definitions ¶
Definitions hold schema definitions. http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.26 RFC draft-wright-json-schema-validation-00, section 5.26
type ID ¶
type ID string
ID represents a Schema ID type which should always be a URI. See draft-bhutton-json-schema-00 section 8.2.1
const EmptyID ID = ""
    EmptyID is used to explicitly define an ID with no value.
func (ID) Add ¶
Add appends the provided path to the id, and removes any anchor data that might be there.
type Reflector ¶
type Reflector struct {
	// BaseSchemaID defines the URI that will be used as a base to determine Schema
	// IDs for models. For example, a base Schema ID of `https://invopop.com/schemas`
	// when defined with a struct called `User{}`, will result in a schema with an
	// ID set to `https://invopop.com/schemas/user`.
	//
	// If no `BaseSchemaID` is provided, we'll take the type's complete package path
	// and use that as a base instead. Set `Anonymous` to try if you do not want to
	// include a schema ID.
	BaseSchemaID ID
	// Anonymous when true will hide the auto-generated Schema ID and provide what is
	// known as an "anonymous schema". As a rule, this is not recommended.
	Anonymous bool
	// AssignAnchor when true will use the original struct's name as an anchor inside
	// every definition, including the root schema. These can be useful for having a
	// reference to the original struct's name in CamelCase instead of the snake-case used
	// by default for URI compatibility.
	//
	// Anchors do not appear to be widely used out in the wild, so at this time the
	// anchors themselves will not be used inside generated schema.
	AssignAnchor bool
	// AllowAdditionalProperties will cause the Reflector to generate a schema
	// without additionalProperties set to 'false' for all struct types. This means
	// the presence of additional keys in JSON objects will not cause validation
	// to fail. Note said additional keys will simply be dropped when the
	// validated JSON is unmarshaled.
	AllowAdditionalProperties bool
	// RequiredFromJSONSchemaTags will cause the Reflector to generate a schema
	// that requires any key tagged with `jsonschema:required`, overriding the
	// default of requiring any key *not* tagged with `json:,omitempty`.
	RequiredFromJSONSchemaTags bool
	// Do not reference definitions. This will remove the top-level $defs map and
	// instead cause the entire structure of types to be output in one tree. The
	// list of type definitions (`$defs`) will not be included.
	DoNotReference bool
	// ExpandedStruct when true will include the reflected type's definition in the
	// root as opposed to a definition with a reference.
	ExpandedStruct bool
	// FieldNameTag will change the tag used to get field names. json tags are used by default.
	FieldNameTag string
	// IgnoredTypes defines a slice of types that should be ignored in the schema,
	// switching to just allowing additional properties instead.
	IgnoredTypes []any
	// Lookup allows a function to be defined that will provide a custom mapping of
	// types to Schema IDs. This allows existing schema documents to be referenced
	// by their ID instead of being embedded into the current schema definitions.
	// Reflected types will never be pointers, only underlying elements.
	Lookup func(reflect.Type) ID
	// Mapper is a function that can be used to map custom Go types to jsonschema schemas.
	Mapper func(reflect.Type) *Schema
	// Namer allows customizing of type names. The default is to use the type's name
	// provided by the reflect package.
	Namer func(reflect.Type) string
	// KeyNamer allows customizing of key names.
	// The default is to use the key's name as is, or the json tag if present.
	// If a json tag is present, KeyNamer will receive the tag's name as an argument, not the original key name.
	KeyNamer func(string) string
	// AdditionalFields allows adding structfields for a given type
	AdditionalFields func(reflect.Type) []reflect.StructField
	// CommentMap is a dictionary of fully qualified go types and fields to comment
	// strings that will be used if a description has not already been provided in
	// the tags. Types and fields are added to the package path using "." as a
	// separator.
	//
	// Type descriptions should be defined like:
	//
	//   map[string]string{"github.com/invopop/jsonschema.Reflector": "A Reflector reflects values into a Schema."}
	//
	// And Fields defined as:
	//
	//   map[string]string{"github.com/invopop/jsonschema.Reflector.DoNotReference": "Do not reference definitions."}
	//
	// See also: AddGoComments
	CommentMap map[string]string
}
    A Reflector reflects values into a Schema.
func (*Reflector) AddGoComments ¶
AddGoComments will update the reflectors comment map with all the comments found in the provided source directories. See the #ExtractGoComments method for more details.
func (*Reflector) ReflectFromType ¶
ReflectFromType generates root schema
func (*Reflector) SetBaseSchemaID ¶
SetBaseSchemaID is a helper use to be able to set the reflectors base schema ID from a string as opposed to then ID instance.
type Schema ¶
type Schema struct {
	// RFC draft-bhutton-json-schema-00
	Version     string      `json:"$schema,omitempty"`     // section 8.1.1
	ID          ID          `json:"$id,omitempty"`         // section 8.2.1
	Anchor      string      `json:"$anchor,omitempty"`     // section 8.2.2
	Ref         string      `json:"$ref,omitempty"`        // section 8.2.3.1
	DynamicRef  string      `json:"$dynamicRef,omitempty"` // section 8.2.3.2
	Definitions Definitions `json:"$defs,omitempty"`       // section 8.2.4
	Comments    string      `json:"$comment,omitempty"`    // section 8.3
	// RFC draft-bhutton-json-schema-00 section 10.2.1 (Sub-schemas with logic)
	AllOf []*Schema `json:"allOf,omitempty"` // section 10.2.1.1
	AnyOf []*Schema `json:"anyOf,omitempty"` // section 10.2.1.2
	OneOf []*Schema `json:"oneOf,omitempty"` // section 10.2.1.3
	Not   *Schema   `json:"not,omitempty"`   // section 10.2.1.4
	// RFC draft-bhutton-json-schema-00 section 10.2.2 (Apply sub-schemas conditionally)
	If               *Schema            `json:"if,omitempty"`               // section 10.2.2.1
	Then             *Schema            `json:"then,omitempty"`             // section 10.2.2.2
	Else             *Schema            `json:"else,omitempty"`             // section 10.2.2.3
	DependentSchemas map[string]*Schema `json:"dependentSchemas,omitempty"` // section 10.2.2.4
	// RFC draft-bhutton-json-schema-00 section 10.3.1 (arrays)
	PrefixItems []*Schema `json:"prefixItems,omitempty"` // section 10.3.1.1
	Items       *Schema   `json:"items,omitempty"`       // section 10.3.1.2  (replaces additionalItems)
	Contains    *Schema   `json:"contains,omitempty"`    // section 10.3.1.3
	// RFC draft-bhutton-json-schema-00 section 10.3.2 (sub-schemas)
	Properties           *orderedmap.OrderedMap[string, *Schema] `json:"properties,omitempty"`           // section 10.3.2.1
	PatternProperties    map[string]*Schema                      `json:"patternProperties,omitempty"`    // section 10.3.2.2
	AdditionalProperties *Schema                                 `json:"additionalProperties,omitempty"` // section 10.3.2.3
	PropertyNames        *Schema                                 `json:"propertyNames,omitempty"`        // section 10.3.2.4
	// RFC draft-bhutton-json-schema-validation-00, section 6
	Type              string              `json:"type,omitempty"`              // section 6.1.1
	Enum              []any               `json:"enum,omitempty"`              // section 6.1.2
	Const             any                 `json:"const,omitempty"`             // section 6.1.3
	MultipleOf        json.Number         `json:"multipleOf,omitempty"`        // section 6.2.1
	Maximum           json.Number         `json:"maximum,omitempty"`           // section 6.2.2
	ExclusiveMaximum  json.Number         `json:"exclusiveMaximum,omitempty"`  // section 6.2.3
	Minimum           json.Number         `json:"minimum,omitempty"`           // section 6.2.4
	ExclusiveMinimum  json.Number         `json:"exclusiveMinimum,omitempty"`  // section 6.2.5
	MaxLength         int                 `json:"maxLength,omitempty"`         // section 6.3.1
	MinLength         int                 `json:"minLength,omitempty"`         // section 6.3.2
	Pattern           string              `json:"pattern,omitempty"`           // section 6.3.3
	MaxItems          int                 `json:"maxItems,omitempty"`          // section 6.4.1
	MinItems          int                 `json:"minItems,omitempty"`          // section 6.4.2
	UniqueItems       bool                `json:"uniqueItems,omitempty"`       // section 6.4.3
	MaxContains       uint                `json:"maxContains,omitempty"`       // section 6.4.4
	MinContains       uint                `json:"minContains,omitempty"`       // section 6.4.5
	MaxProperties     int                 `json:"maxProperties,omitempty"`     // section 6.5.1
	MinProperties     int                 `json:"minProperties,omitempty"`     // section 6.5.2
	Required          []string            `json:"required,omitempty"`          // section 6.5.3
	DependentRequired map[string][]string `json:"dependentRequired,omitempty"` // section 6.5.4
	// RFC draft-bhutton-json-schema-validation-00, section 7
	Format string `json:"format,omitempty"`
	// RFC draft-bhutton-json-schema-validation-00, section 8
	ContentEncoding  string  `json:"contentEncoding,omitempty"`  // section 8.3
	ContentMediaType string  `json:"contentMediaType,omitempty"` // section 8.4
	ContentSchema    *Schema `json:"contentSchema,omitempty"`    // section 8.5
	// RFC draft-bhutton-json-schema-validation-00, section 9
	Title       string `json:"title,omitempty"`       // section 9.1
	Description string `json:"description,omitempty"` // section 9.1
	Default     any    `json:"default,omitempty"`     // section 9.2
	Deprecated  bool   `json:"deprecated,omitempty"`  // section 9.3
	ReadOnly    bool   `json:"readOnly,omitempty"`    // section 9.4
	WriteOnly   bool   `json:"writeOnly,omitempty"`   // section 9.4
	Examples    []any  `json:"examples,omitempty"`    // section 9.5
	Extras map[string]any `json:"-"`
	// contains filtered or unexported fields
}
    Schema represents a JSON Schema object type. RFC draft-bhutton-json-schema-00 section 4.3
func Reflect ¶
Reflect reflects to Schema from a value using the default Reflector
Example ¶
package main
import (
	"encoding/json"
	"fmt"
	"time"
	"github.com/invopop/jsonschema"
)
type SampleUser struct {
	ID          int            `json:"id"`
	Name        string         `json:"name" jsonschema:"title=the name,description=The name of a friend,example=joe,example=lucy,default=alex"`
	Friends     []int          `json:"friends,omitempty" jsonschema_description:"The list of IDs, omitted when empty"`
	Tags        map[string]any `json:"tags,omitempty" jsonschema_extras:"a=b,foo=bar,foo=bar1"`
	BirthDate   time.Time      `json:"birth_date,omitempty" jsonschema:"oneof_required=date"`
	YearOfBirth string         `json:"year_of_birth,omitempty" jsonschema:"oneof_required=year"`
	Metadata    any            `json:"metadata,omitempty" jsonschema:"oneof_type=string;array"`
	FavColor    string         `json:"fav_color,omitempty" jsonschema:"enum=red,enum=green,enum=blue"`
}
func main() {
	s := jsonschema.Reflect(&SampleUser{})
	data, err := json.MarshalIndent(s, "", "  ")
	if err != nil {
		panic(err.Error())
	}
	fmt.Println(string(data))
}
Output: { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://github.com/invopop/jsonschema_test/sample-user", "$ref": "#/$defs/SampleUser", "$defs": { "SampleUser": { "oneOf": [ { "required": [ "birth_date" ], "title": "date" }, { "required": [ "year_of_birth" ], "title": "year" } ], "properties": { "id": { "type": "integer" }, "name": { "type": "string", "title": "the name", "description": "The name of a friend", "default": "alex", "examples": [ "joe", "lucy" ] }, "friends": { "items": { "type": "integer" }, "type": "array", "description": "The list of IDs, omitted when empty" }, "tags": { "type": "object", "a": "b", "foo": [ "bar", "bar1" ] }, "birth_date": { "type": "string", "format": "date-time" }, "year_of_birth": { "type": "string" }, "metadata": { "oneOf": [ { "type": "string" }, { "type": "array" } ] }, "fav_color": { "type": "string", "enum": [ "red", "green", "blue" ] } }, "additionalProperties": false, "type": "object", "required": [ "id", "name" ] } } }
func ReflectFromType ¶
ReflectFromType generates root schema using the default Reflector
func (*Schema) MarshalJSON ¶
MarshalJSON is used to serialize a schema object or boolean.
func (*Schema) UnmarshalJSON ¶
UnmarshalJSON is used to parse a schema object or boolean.