README

Go JSON Schema Reflection

Build Status Gitter chat Go Report Card GoDoc

This package can be used to generate JSON Schemas from Go types through reflection.

  • Supports arbitrarily complex types, including interface{}, maps, slices, etc.
  • Supports json-schema features such as minLength, maxLength, pattern, format, etc.
  • Supports simple string and numeric enums.
  • Supports custom property fields via the jsonschema_extras struct tag.

Example

The following Go type:

type TestUser 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]interface{} `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      interface{}            `json:"metadata,omitempty" jsonschema:"oneof_type=string;array"`
  FavColor      string                 `json:"fav_color,omitempty" jsonschema:"enum=red,enum=green,enum=blue"`
}

Results in following JSON Schema:

jsonschema.Reflect(&TestUser{})
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "$ref": "#/definitions/TestUser",
  "definitions": {
    "TestUser": {
      "type": "object",
      "properties": {
        "metadata": {
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "array"
            }
          ]
        },
        "birth_date": {
          "type": "string",
          "format": "date-time"
        },
        "friends": {
          "type": "array",
          "items": {
            "type": "integer"
          },
          "description": "The list of IDs, omitted when empty"
        },
        "id": {
          "type": "integer"
        },
        "name": {
          "type": "string",
          "title": "the name",
          "description": "The name of a friend",
          "default": "alex",
          "examples": [
            "joe",
            "lucy"
          ]
        },
        "tags": {
          "type": "object",
          "patternProperties": {
            ".*": {
              "additionalProperties": true
            }
          },
          "a": "b",
          "foo": [
            "bar",
            "bar1"
          ]
        },
        "fav_color": {
          "type": "string",
          "enum": [
            "red",
            "green",
            "blue"
          ]
        }
      },
      "additionalProperties": false,
      "required": ["id", "name"],
      "oneOf": [
        {
          "required": [
            "birth_date"
          ],
          "title": "date"
        },
        {
          "required": [
            "year_of_birth"
          ],
          "title": "year"
        }
      ]
    }
  }
}

Configurable behaviour

The behaviour of the schema generator can be altered with parameters when a jsonschema.Reflector instance is created.

ExpandedStruct

If set to true, makes the top level struct not to reference itself in the definitions. But type passed should be a struct type.

eg.

type GrandfatherType struct {
	FamilyName string `json:"family_name" jsonschema:"required"`
}

type SomeBaseType struct {
	SomeBaseProperty int `json:"some_base_property"`
	// The jsonschema required tag is nonsensical for private and ignored properties.
	// Their presence here tests that the fields *will not* be required in the output
	// schema, even if they are tagged required.
	somePrivateBaseProperty            string `json:"i_am_private" jsonschema:"required"`
	SomeIgnoredBaseProperty            string `json:"-" jsonschema:"required"`
	SomeSchemaIgnoredProperty          string `jsonschema:"-,required"`
	SomeUntaggedBaseProperty           bool   `jsonschema:"required"`
	someUnexportedUntaggedBaseProperty bool
	Grandfather                        GrandfatherType `json:"grand"`
}

will output:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "required": [
    "some_base_property",
    "grand",
    "SomeUntaggedBaseProperty"
  ],
  "properties": {
    "SomeUntaggedBaseProperty": {
      "type": "boolean"
    },
    "grand": {
      "$schema": "http://json-schema.org/draft-04/schema#",
      "$ref": "#/definitions/GrandfatherType"
    },
    "some_base_property": {
      "type": "integer"
    }
  },
  "type": "object",
  "definitions": {
    "GrandfatherType": {
      "required": [
        "family_name"
      ],
      "properties": {
        "family_name": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "type": "object"
    }
  }
}
PreferYAMLSchema

JSON schemas can also be used to validate YAML, however YAML frequently uses different identifiers to JSON indicated by the yaml: tag. The Reflector will by default prefer json: tags over yaml: tags (and only use the latter if the former are not present). This behavior can be changed via the PreferYAMLSchema flag, that will switch this behavior: yaml: tags will be preferred over json: tags.

With PreferYAMLSchema: true, the following struct:

type Person struct {
	FirstName string `json:"FirstName" yaml:"first_name"`
}

would result in this schema:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "$ref": "#/definitions/TestYamlAndJson",
  "definitions": {
    "Person": {
      "required": ["first_name"],
      "properties": {
        "first_name": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "type": "object"
    }
  }
}

whereas without the flag one obtains:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "$ref": "#/definitions/TestYamlAndJson",
  "definitions": {
    "Person": {
      "required": ["FirstName"],
      "properties": {
        "first_name": {
          "type": "string"
        }
      },
      "additionalProperties": false,
      "type": "object"
    }
  }
}
Expand ▾ Collapse ▴

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

    Constants

    This section is empty.

    Variables

    View Source
    var Version = "http://json-schema.org/draft-04/schema#"

      Version is the JSON Schema version. If extending JSON Schema with custom values use a custom URI. RFC draft-wright-json-schema-00, section 6

      Functions

      This section is empty.

      Types

      type Definitions

      type Definitions map[string]*Type

        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 Reflector

        type Reflector struct {
        	// AllowAdditionalProperties will cause the Reflector to generate a schema
        	// with additionalProperties to 'true' 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
        
        	// YAMLEmbeddedStructs will cause the Reflector to generate a schema that does
        	// not inline embedded structs. This should be enabled if the JSON schemas are
        	// used with yaml.Marshal/Unmarshal.
        	YAMLEmbeddedStructs bool
        
        	// Prefer yaml: tags over json: tags to generate the schema even if json: tags
        	// are present
        	PreferYAMLSchema bool
        
        	// ExpandedStruct will cause the toplevel definitions of the schema not
        	// be referenced itself to a definition.
        	ExpandedStruct bool
        
        	// Do not reference definitions.
        	// All types are still registered under the "definitions" top-level object,
        	// but instead of $ref fields in containing types, the entire definition
        	// of the contained type is inserted.
        	// This will cause the entire structure of types to be output in one tree.
        	DoNotReference bool
        
        	// Use package paths as well as type names, to avoid conflicts.
        	// Without this setting, if two packages contain a type with the same name,
        	// and both are present in a schema, they will conflict and overwrite in
        	// the definition map and produce bad output.  This is particularly
        	// noticeable when using DoNotReference.
        	FullyQualifyTypeNames bool
        
        	// IgnoredTypes defines a slice of types that should be ignored in the schema,
        	// switching to just allowing additional properties instead.
        	IgnoredTypes []interface{}
        
        	// TypeMapper is a function that can be used to map custom Go types to jsconschema types.
        	TypeMapper func(reflect.Type) *Type
        
        	// TypeNamer allows customizing of type names
        	TypeNamer func(reflect.Type) string
        
        	// AdditionalFields allows adding structfields for a given type
        	AdditionalFields func(reflect.Type) []reflect.StructField
        }

          A Reflector reflects values into a Schema.

          func (*Reflector) Reflect

          func (r *Reflector) Reflect(v interface{}) *Schema

            Reflect reflects to Schema from a value.

            func (*Reflector) ReflectFromType

            func (r *Reflector) ReflectFromType(t reflect.Type) *Schema

              ReflectFromType generates root schema

              type Schema

              type Schema struct {
              	*Type
              	Definitions Definitions
              }

                Schema is the root schema. RFC draft-wright-json-schema-00, section 4.5

                func Reflect

                func Reflect(v interface{}) *Schema

                  Reflect reflects to Schema from a value using the default Reflector

                  func ReflectFromType

                  func ReflectFromType(t reflect.Type) *Schema

                    ReflectFromType generates root schema using the default Reflector

                    func (*Schema) MarshalJSON

                    func (s *Schema) MarshalJSON() ([]byte, error)

                    type Type

                    type Type struct {
                    	// RFC draft-wright-json-schema-00
                    	Version string `json:"$schema,omitempty"` // section 6.1
                    	Ref     string `json:"$ref,omitempty"`    // section 7
                    	// RFC draft-wright-json-schema-validation-00, section 5
                    	MultipleOf           int                    `json:"multipleOf,omitempty"`           // section 5.1
                    	Maximum              int                    `json:"maximum,omitempty"`              // section 5.2
                    	ExclusiveMaximum     bool                   `json:"exclusiveMaximum,omitempty"`     // section 5.3
                    	Minimum              int                    `json:"minimum,omitempty"`              // section 5.4
                    	ExclusiveMinimum     bool                   `json:"exclusiveMinimum,omitempty"`     // section 5.5
                    	MaxLength            int                    `json:"maxLength,omitempty"`            // section 5.6
                    	MinLength            int                    `json:"minLength,omitempty"`            // section 5.7
                    	Pattern              string                 `json:"pattern,omitempty"`              // section 5.8
                    	AdditionalItems      *Type                  `json:"additionalItems,omitempty"`      // section 5.9
                    	Items                *Type                  `json:"items,omitempty"`                // section 5.9
                    	MaxItems             int                    `json:"maxItems,omitempty"`             // section 5.10
                    	MinItems             int                    `json:"minItems,omitempty"`             // section 5.11
                    	UniqueItems          bool                   `json:"uniqueItems,omitempty"`          // section 5.12
                    	MaxProperties        int                    `json:"maxProperties,omitempty"`        // section 5.13
                    	MinProperties        int                    `json:"minProperties,omitempty"`        // section 5.14
                    	Required             []string               `json:"required,omitempty"`             // section 5.15
                    	Properties           *orderedmap.OrderedMap `json:"properties,omitempty"`           // section 5.16
                    	PatternProperties    map[string]*Type       `json:"patternProperties,omitempty"`    // section 5.17
                    	AdditionalProperties json.RawMessage        `json:"additionalProperties,omitempty"` // section 5.18
                    	Dependencies         map[string]*Type       `json:"dependencies,omitempty"`         // section 5.19
                    	Enum                 []interface{}          `json:"enum,omitempty"`                 // section 5.20
                    	Type                 string                 `json:"type,omitempty"`                 // section 5.21
                    	AllOf                []*Type                `json:"allOf,omitempty"`                // section 5.22
                    	AnyOf                []*Type                `json:"anyOf,omitempty"`                // section 5.23
                    	OneOf                []*Type                `json:"oneOf,omitempty"`                // section 5.24
                    	Not                  *Type                  `json:"not,omitempty"`                  // section 5.25
                    	Definitions          Definitions            `json:"definitions,omitempty"`          // section 5.26
                    	// RFC draft-wright-json-schema-validation-00, section 6, 7
                    	Title       string        `json:"title,omitempty"`       // section 6.1
                    	Description string        `json:"description,omitempty"` // section 6.1
                    	Default     interface{}   `json:"default,omitempty"`     // section 6.2
                    	Format      string        `json:"format,omitempty"`      // section 7
                    	Examples    []interface{} `json:"examples,omitempty"`    // section 7.4
                    	// RFC draft-wright-json-schema-hyperschema-00, section 4
                    	Media          *Type  `json:"media,omitempty"`          // section 4.3
                    	BinaryEncoding string `json:"binaryEncoding,omitempty"` // section 4.3
                    
                    	Extras map[string]interface{} `json:"-"`
                    }

                      Type represents a JSON Schema object type.

                      func (*Type) MarshalJSON

                      func (t *Type) MarshalJSON() ([]byte, error)

                      Source Files