jsonschema

package module
v6.0.0-beta1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 8, 2024 License: Apache-2.0 Imports: 24 Imported by: 0

README

jsonschema v6.0.0-beta1

License GoDoc Go Report Card Build Status codecov

Examples Changelog

Library Features

  • pass JSON-Schema-Test-Suite excluding optional(compare with other impls at bowtie)
    • draft-04
    • draft-06
    • draft-07
    • draft/2019-09
    • draft/2020-12
  • detect infinite loop traps
    • $schema cycle
    • validation cycle
  • custom $schema url
  • vocabulary based validation
  • custom regex engine
  • format assertions
    • flag to enable in draft >= 2019-09
    • custom format registration
    • built-in formats
      • regex, uuid
      • ipv4, ipv6
      • hostname, email
      • date, time, date-time, duration
      • json-pointer, relative-json-pointer
      • uri, uri-reference, uri-template
      • iri, iri-reference
      • period, semver
  • content assertions
    • flag to enable in draft >= 7
    • contentEncoding
      • base64
      • custom
    • contentMediaType
      • application/json
      • custom
    • contentSchema
  • errors
    • introspectable
    • hierarchy
      • alternative display with #
    • output
      • flag
      • basic
      • detailed
  • custom vocabulary
    • enable via $vocabulary for draft >=2019-19
    • enable via flag for draft <= 7
  • mixed dialect support

CLI

to install: go install github.com/santhosh-tekuri/jsonschema/cmd/jv@latest

Usage: jv [OPTIONS] SCHEMA [INSTANCE...]

Options:
  -c, --assert-content    Enable content assertions with draft >= 7
  -f, --assert-format     Enable format assertions with draft >= 2019
      --cacert pem-file   Use the specified pem-file to verify the peer. The file may contain multiple CA certificates
  -d, --draft version     Draft version used when '$schema' is missing. Valid values 4, 6, 7, 2019, 2020 (default 2020)
  -h, --help              Print help information
  -k, --insecure          Use insecure TLS connection
  -o, --output format     Output format. Valid values simple, alt, flag, basic, detailed (default "simple")
  -q, --quiet             Do not print errors
  -v, --version           Print build information
  • exit code 1 for validation erros, 2 for usage errors
  • validate both schema and multiple instances
  • support both json and yaml files
  • support standard input, use -
  • quite mode with parsable output
  • http(s) url support
    • custom certs for validation, use --cacert
    • flag to skip certificate verification, use --insecure

Documentation

Overview

Example (CustomContentEndocing)

Example_customContentEncoding shows how to define "hex" contentEncoding.

schema, err := jsonschema.UnmarshalJSON(strings.NewReader(`{"type": "string", "contentEncoding": "hex"}`))
if err != nil {
	log.Fatal(err)
}
inst := "abcxyz"

c := jsonschema.NewCompiler()
c.RegisterContentEncoding(&jsonschema.Decoder{
	Name:   "hex",
	Decode: hex.DecodeString,
})
c.AssertContent()
if err := c.AddResource("schema.json", schema); err != nil {
	log.Fatal(err)
}
sch, err := c.Compile("schema.json")
if err != nil {
	log.Fatal(err)
}
err = sch.Validate(inst)
fmt.Println("valid:", err == nil)
Output:

valid: false
Example (CustomContentMediaType)

Example_customContentMediaType shows how to define "application/xml" contentMediaType.

schema, err := jsonschema.UnmarshalJSON(strings.NewReader(`{"type": "string", "contentMediaType": "application/xml"}`))
if err != nil {
	log.Fatal(err)
}
inst := "<abc></def>"

c := jsonschema.NewCompiler()
c.RegisterContentMediaType(&jsonschema.MediaType{
	Name: "application/xml",
	Validate: func(b []byte) error {
		return xml.Unmarshal(b, new(any))
	},
	UnmarshalJSON: nil, // xml is not json-compatiable format
})
c.AssertContent()
if err := c.AddResource("schema.json", schema); err != nil {
	log.Fatal(err)
}
sch, err := c.Compile("schema.json")
if err != nil {
	log.Fatal(err)
}
err = sch.Validate(inst)
fmt.Println("valid:", err == nil)
Output:

valid: false
Example (CustomFormat)
validatePalindrome := func(v any) error {
	s, ok := v.(string)
	if !ok {
		return nil
	}
	var runes []rune
	for _, r := range s {
		runes = append(runes, r)
	}
	for i, j := 0, len(runes)-1; i <= j; i, j = i+1, j-1 {
		if runes[i] != runes[j] {
			return fmt.Errorf("no match for rune at %d", i)
		}
	}
	return nil
}

schema, err := jsonschema.UnmarshalJSON(strings.NewReader(`{"type": "string", "format": "palindrome"}`))
if err != nil {
	log.Fatal(err)
}
inst := "hello world"

c := jsonschema.NewCompiler()
c.RegisterFormat(&jsonschema.Format{
	Name:     "palindrome",
	Validate: validatePalindrome,
})
c.AssertFormat()
if err := c.AddResource("schema.json", schema); err != nil {
	log.Fatal(err)
}
sch, err := c.Compile("schema.json")
if err != nil {
	log.Fatal(err)
}
err = sch.Validate(inst)
fmt.Println("valid:", err == nil)
Output:

valid: false
Example (CustomRegexpEngine)

Example_customRegexpEngine shows how to use dlclark/regexp2 instead of regexp from standard library.

package main

import (
	"fmt"
	"log"
	"strings"

	"github.com/dlclark/regexp2"
	"github.com/santhosh-tekuri/jsonschema/v6"
)

type dlclarkRegexp regexp2.Regexp

func (re *dlclarkRegexp) MatchString(s string) bool {
	matched, err := (*regexp2.Regexp)(re).MatchString(s)
	return err == nil && matched
}

func (re *dlclarkRegexp) String() string {
	return (*regexp2.Regexp)(re).String()
}

func dlclarkCompile(s string) (jsonschema.Regexp, error) {
	re, err := regexp2.Compile(s, regexp2.ECMAScript)
	if err != nil {
		return nil, err
	}
	return (*dlclarkRegexp)(re), nil
}

// Example_customRegexpEngine shows how to use dlclark/regexp2
// instead of regexp from standard library.
func main() {
	// golang regexp does not support escape sequence: `\c`
	schema, err := jsonschema.UnmarshalJSON(strings.NewReader(`{
		"type": "string",
		"pattern": "^\\cc$"
	}`))
	if err != nil {
		log.Fatal(err)
	}
	inst, err := jsonschema.UnmarshalJSON(strings.NewReader(`"\u0003"`))
	if err != nil {
		log.Fatal(err)
	}

	c := jsonschema.NewCompiler()
	c.UseRegexpEngine(dlclarkCompile)
	if err := c.AddResource("schema.json", schema); err != nil {
		log.Fatal(err)
	}

	sch, err := c.Compile("schema.json")
	if err != nil {
		log.Fatal(err)
	}
	err = sch.Validate(inst)
	fmt.Println("valid:", err == nil)
}
Output:

valid: true
Example (FromFiles)
schemaFile := "./testdata/examples/schema.json"
instanceFile := "./testdata/examples/instance.json"

c := jsonschema.NewCompiler()
sch, err := c.Compile(schemaFile)
if err != nil {
	log.Fatal(err)
}

f, err := os.Open(instanceFile)
if err != nil {
	log.Fatal(err)
}
inst, err := jsonschema.UnmarshalJSON(f)
if err != nil {
	log.Fatal(err)
}

err = sch.Validate(inst)
fmt.Println("valid:", err == nil)
Output:

valid: true
Example (FromHTTPS)
package main

import (
	"crypto/tls"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/santhosh-tekuri/jsonschema/v6"
)

type HTTPURLLoader http.Client

func (l *HTTPURLLoader) Load(url string) (any, error) {
	client := (*http.Client)(l)
	resp, err := client.Get(url)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		_ = resp.Body.Close()
		return nil, fmt.Errorf("%s returned status code %d", url, resp.StatusCode)
	}
	defer resp.Body.Close()

	return jsonschema.UnmarshalJSON(resp.Body)
}

func newHTTPURLLoader(insecure bool) *HTTPURLLoader {
	httpLoader := HTTPURLLoader(http.Client{
		Timeout: 15 * time.Second,
	})
	if insecure {
		httpLoader.Transport = &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		}
	}
	return &httpLoader
}

func main() {
	schemaURL := "https://raw.githubusercontent.com/santhosh-tekuri/boon/main/tests/examples/schema.json"
	instanceFile := "./testdata/examples/instance.json"

	loader := jsonschema.SchemeURLLoader{
		"file":  jsonschema.FileLoader{},
		"http":  newHTTPURLLoader(false),
		"https": newHTTPURLLoader(false),
	}

	c := jsonschema.NewCompiler()
	c.UseLoader(loader)
	sch, err := c.Compile(schemaURL)
	if err != nil {
		log.Fatal(err)
	}

	f, err := os.Open(instanceFile)
	if err != nil {
		log.Fatal(err)
	}
	inst, err := jsonschema.UnmarshalJSON(f)
	if err != nil {
		log.Fatal(err)
	}

	err = sch.Validate(inst)
	fmt.Println("valid:", err == nil)
}
Output:

valid: true
Example (FromStrings)
catSchema, err := jsonschema.UnmarshalJSON(strings.NewReader(`{
        "type": "object",
        "properties": {
            "speak": { "const": "meow" }
        },
        "required": ["speak"]
    }`))
if err != nil {
	log.Fatal(err)
}
// note that dog.json is loaded from file ./testdata/examples/dog.json
petSchema, err := jsonschema.UnmarshalJSON(strings.NewReader(`{
        "oneOf": [
            { "$ref": "dog.json" },
            { "$ref": "cat.json" }
        ]
    }`))
if err != nil {
	log.Fatal(err)
}
inst, err := jsonschema.UnmarshalJSON(strings.NewReader(`{"speak": "bow"}`))
if err != nil {
	log.Fatal(err)
}

c := jsonschema.NewCompiler()
if err := c.AddResource("./testdata/examples/cat.json", catSchema); err != nil {
	log.Fatal(err)
}
if err := c.AddResource("./testdata/examples/pet.json", petSchema); err != nil {
	log.Fatal(err)
}
sch, err := c.Compile("./testdata/examples/pet.json")
if err != nil {
	log.Fatal(err)
}
err = sch.Validate(inst)
fmt.Println("valid:", err == nil)
Output:

valid: true
Example (Vocab_discriminator)
package main

import (
	"fmt"
	"log"
	"strings"

	"github.com/santhosh-tekuri/jsonschema/v6"
)

// SchemaExt --

type discriminator struct {
	pname  string
	values map[string]*jsonschema.Schema
}

func (d *discriminator) Validate(ctx *jsonschema.ValidatorContext, v any) {
	obj, ok := v.(map[string]any)
	if !ok {
		return
	}
	pvalue, ok := obj[d.pname]
	if !ok {
		return
	}
	value, ok := pvalue.(string)
	if !ok {
		return
	}
	sch := d.values[value]
	if sch == nil {
		return
	}
	if err := ctx.Validate(sch, v, nil); err != nil {
		ctx.AddErr(err)
	} else {
		ctx.EvaluatedProp(d.pname)
	}
}

// Vocab --

func discriminatorVocab() *jsonschema.Vocabulary {
	url := "http://example.com/meta/discriminator"
	schema, err := jsonschema.UnmarshalJSON(strings.NewReader(`{
		"discriminator": {
			"type": "object",
			"minProperties": 1,
			"maxProperties": 1,
			"patternProperties": {
				".*": {
					"type": "object",
					"patternProperties": {
						".*": {
							"$ref": "https://json-schema.org/draft/2020-12/schema"
						}
					}
				}
			}
		}
	}`))
	if err != nil {
		log.Fatal(err)
	}

	c := jsonschema.NewCompiler()
	if err := c.AddResource(url, schema); err != nil {
		log.Fatal(err)
	}
	sch, err := c.Compile(url)
	if err != nil {
		log.Fatal(err)
	}

	return &jsonschema.Vocabulary{
		URL:    url,
		Schema: sch,
		Subschemas: jsonschema.Subschemas{
			"discriminator": {
				{jsonschema.PosProp, jsonschema.PosProp},
			},
		},
		Compile: compileDiscriminator,
	}
}

func compileDiscriminator(ctx *jsonschema.CompilerContext, obj map[string]any) (jsonschema.SchemaExt, error) {
	v, ok := obj["discriminator"]
	if !ok {
		return nil, nil
	}
	d, ok := v.(map[string]any)
	if !ok {
		return nil, nil
	}
	var pname string
	var pvalue any
	for key, value := range d {
		pname = key
		pvalue = value
		break
	}
	values := map[string]*jsonschema.Schema{}
	vm, ok := pvalue.(map[string]any)
	if !ok {
		return nil, nil
	}
	for value := range vm {
		values[value] = ctx.Enqueue([]string{"discriminator", pname, value})
	}
	return &discriminator{pname, values}, nil
}

// Example --

func main() {
	// if kind is fish, swimmingSpeed is required
	// if kind is dog, runningSpeed is required
	schema, err := jsonschema.UnmarshalJSON(strings.NewReader(`{
		"type": "object",
		"properties": {
			"kind": { "type": "string" }
		},
		"required": ["kind"],
		"discriminator": {
			"kind": {
				"fish": {
					"type": "object",
					"properties": {
						"swimmingSpeed": { "type": "number" }
					},
					"required": ["swimmingSpeed"]
				},
				"dog": {
					"type": "object",
					"properties": {
						"runningSpeed": { "type": "number" }
					},
					"required": ["runningSpeed"]
				}
			}
		}
	}`))
	if err != nil {
		fmt.Println("xxx", err)
		log.Fatal(err)
	}
	inst, err := jsonschema.UnmarshalJSON(strings.NewReader(`{
		"kind": "fish",
		"runningSpeed": 5
	}`))
	if err != nil {
		log.Fatal(err)
	}
	c := jsonschema.NewCompiler()
	c.AssertVocabs()
	c.RegisterVocabulary(discriminatorVocab())
	if err := c.AddResource("schema.json", schema); err != nil {
		log.Fatal(err)
	}
	sch, err := c.Compile("schema.json")
	if err != nil {
		log.Fatal(err)
	}

	err = sch.Validate(inst)
	fmt.Println("valid:", err == nil)
}
Output:

valid: false
Example (Vocab_uniquekeys)
package main

import (
	"fmt"
	"log"
	"strings"

	"github.com/santhosh-tekuri/jsonschema/v6"
	"golang.org/x/text/message"
)

// SchemaExt --

type uniqueKeys struct {
	pname string
}

func (s *uniqueKeys) Validate(ctx *jsonschema.ValidatorContext, v any) {
	arr, ok := v.([]any)
	if !ok {
		return
	}
	var keys []any
	for _, item := range arr {
		obj, ok := item.(map[string]any)
		if !ok {
			continue
		}
		key, ok := obj[s.pname]
		if ok {
			keys = append(keys, key)
		}
	}

	i, j, err := ctx.Duplicates(keys)
	if err != nil {
		ctx.AddErr(err)
		return
	}
	if i != -1 {
		ctx.AddError(&UniqueKeys{Key: s.pname, Duplicates: []int{i, j}})
	}
}

// Vocab --

func uniqueKeysVocab() *jsonschema.Vocabulary {
	url := "http://example.com/meta/unique-keys"
	schema, err := jsonschema.UnmarshalJSON(strings.NewReader(`{
		"properties": {
			"uniqueKeys": { "type": "string" }
		}
	}`))
	if err != nil {
		log.Fatal(err)
	}

	c := jsonschema.NewCompiler()
	if err := c.AddResource(url, schema); err != nil {
		log.Fatal(err)
	}
	sch, err := c.Compile(url)
	if err != nil {
		log.Fatal(err)
	}

	return &jsonschema.Vocabulary{
		URL:     url,
		Schema:  sch,
		Compile: compileUniqueKeys,
	}
}

func compileUniqueKeys(ctx *jsonschema.CompilerContext, obj map[string]any) (jsonschema.SchemaExt, error) {
	v, ok := obj["uniqueKeys"]
	if !ok {
		return nil, nil
	}
	s, ok := v.(string)
	if !ok {
		return nil, nil
	}
	return &uniqueKeys{pname: s}, nil
}

// ErrorKind --

type UniqueKeys struct {
	Key        string
	Duplicates []int
}

func (*UniqueKeys) KeywordPath() []string {
	return []string{"uniqueKeys"}
}

func (k *UniqueKeys) LocalizedString(p *message.Printer) string {
	return p.Sprintf("items at %d and %d have same %s", k.Duplicates[0], k.Duplicates[1], k.Key)
}

// Example --

func main() {
	schema, err := jsonschema.UnmarshalJSON(strings.NewReader(`{
		"uniqueKeys": "id"
	}`))
	if err != nil {
		log.Fatal(err)
	}
	inst, err := jsonschema.UnmarshalJSON(strings.NewReader(`[
		{ "id": 1, "name": "alice" },
		{ "id": 2, "name": "bob" },
		{ "id": 1, "name": "scott" }
	]`))
	if err != nil {
		log.Fatal(err)
	}

	c := jsonschema.NewCompiler()
	c.AssertVocabs()
	c.RegisterVocabulary(uniqueKeysVocab())
	if err := c.AddResource("schema.json", schema); err != nil {
		log.Fatal(err)
	}
	sch, err := c.Compile("schema.json")
	if err != nil {
		log.Fatal(err)
	}

	err = sch.Validate(inst)
	fmt.Println("valid:", err == nil)
}
Output:

valid: false

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	Draft4 = &Draft{
		version: 4,
		url:     "http://json-schema.org/draft-04/schema",
		id:      "id",
		subschemas: Subschemas{

			"definitions": {{PosProp}},
			"not":         {{}},
			"allOf":       {{PosItem}},
			"anyOf":       {{PosItem}},
			"oneOf":       {{PosItem}},

			"properties":           {{PosProp}},
			"additionalProperties": {{}},
			"patternProperties":    {{PosProp}},

			"items":           {{}, {PosItem}},
			"additionalItems": {{}},
			"dependencies":    {{PosProp}},
		},
		vocabPrefix:   "",
		allVocabs:     map[string]*Schema{},
		defaultVocabs: []string{},
	}

	Draft6 = &Draft{
		version: 6,
		url:     "http://json-schema.org/draft-06/schema",
		id:      "$id",
		subschemas: joinMaps(Draft4.subschemas, Subschemas{
			"propertyNames": {{}},
			"contains":      {{}},
		}),
		vocabPrefix:   "",
		allVocabs:     map[string]*Schema{},
		defaultVocabs: []string{},
	}

	Draft7 = &Draft{
		version: 7,
		url:     "http://json-schema.org/draft-07/schema",
		id:      "$id",
		subschemas: joinMaps(Draft6.subschemas, Subschemas{
			"if":   {{}},
			"then": {{}},
			"else": {{}},
		}),
		vocabPrefix:   "",
		allVocabs:     map[string]*Schema{},
		defaultVocabs: []string{},
	}

	Draft2019 = &Draft{
		version: 2019,
		url:     "https://json-schema.org/draft/2019-09/schema",
		id:      "$id",
		subschemas: joinMaps(Draft7.subschemas, Subschemas{
			"$defs":                 {{PosProp}},
			"dependentSchemas":      {{PosProp}},
			"unevaluatedProperties": {{}},
			"unevaluatedItems":      {{}},
			"contentSchema":         {{}},
		}),
		vocabPrefix: "https://json-schema.org/draft/2019-09/vocab/",
		allVocabs: map[string]*Schema{
			"core":       nil,
			"applicator": nil,
			"validation": nil,
			"meta-data":  nil,
			"format":     nil,
			"content":    nil,
		},
		defaultVocabs: []string{"core", "applicator", "validation"},
	}

	Draft2020 = &Draft{
		version: 2020,
		url:     "https://json-schema.org/draft/2020-12/schema",
		id:      "$id",
		subschemas: joinMaps(Draft2019.subschemas, Subschemas{
			"prefixItems": {{PosItem}},
		}),
		vocabPrefix: "https://json-schema.org/draft/2020-12/vocab/",
		allVocabs: map[string]*Schema{
			"core":              nil,
			"applicator":        nil,
			"unevaluated":       nil,
			"validation":        nil,
			"meta-data":         nil,
			"format-annotation": nil,
			"format-assertion":  nil,
			"content":           nil,
		},
		defaultVocabs: []string{"core", "applicator", "unevaluated", "validation"},
	}
)

Functions

func UnmarshalJSON

func UnmarshalJSON(r io.Reader) (any, error)

UnmarshalJSON unmarshals into [any] without losing number precision using json.Number.

Types

type AnchorNotFoundError

type AnchorNotFoundError struct {
	URL       string
	Reference string
}

func (*AnchorNotFoundError) Error

func (e *AnchorNotFoundError) Error() string

type Bug

type Bug struct {
	Msg string
}

func (*Bug) Error

func (e *Bug) Error() string

type Compiler

type Compiler struct {
	// contains filtered or unexported fields
}

Compiler compiles json schema into *Schema.

func NewCompiler

func NewCompiler() *Compiler

func (*Compiler) AddResource

func (c *Compiler) AddResource(url string, doc any) error

AddResource adds schema resource which gets used later in reference resolution.

The argument url can be file path or url. Any fragment in url is ignored.

func (*Compiler) AssertContent

func (c *Compiler) AssertContent()

AssertContent enables content assertions.

Content assertions include keywords: - contentEncoding - contentMediaType - contentSchema

Default behavior is always disabled.

func (*Compiler) AssertFormat

func (c *Compiler) AssertFormat()

AssertFormat always enables format assertions.

Default Behavior: for draft-07: enabled. for draft/2019-09: disabled unless metaschema says `format` vocabulary is required. for draft/2020-12: disabled unless metaschema says `format-assertion` vocabulary is required.

func (*Compiler) AssertVocabs

func (c *Compiler) AssertVocabs()

AssertVocabs always enables user-defined vocabularies assertions.

Default Behavior: for draft-07: enabled. for draft/2019-09: disabled unless metaschema enables a vocabulary. for draft/2020-12: disabled unless metaschema enables a vocabulary.

func (*Compiler) Compile

func (c *Compiler) Compile(loc string) (*Schema, error)

Compile compiles json-schema at gven loc.

func (*Compiler) DefaultDraft

func (c *Compiler) DefaultDraft(d *Draft)

DefaultDraft overrides the draft used to compile schemas without `$schema` field.

By default, this library uses the latest draft supprted.

The use of this option is HIGHLY encouraged to ensure continued correct operation of your schema. The current default value will not stay the same overtime.

func (*Compiler) MustCompile

func (c *Compiler) MustCompile(loc string) *Schema

MustCompile is like [Compile] but panics if compilation fails. It simplifies safe initialization of global variables holding compiled schema.

func (*Compiler) RegisterContentEncoding

func (c *Compiler) RegisterContentEncoding(d *Decoder)

RegisterContentEncoding registers custom contentEncoding.

NOTE: content assertions are disabled by default. see Compiler.AssertContent.

func (*Compiler) RegisterContentMediaType

func (c *Compiler) RegisterContentMediaType(mt *MediaType)

RegisterContentMediaType registers custom contentMediaType.

NOTE: content assertions are disabled by default. see Compiler.AssertContent.

func (*Compiler) RegisterFormat

func (c *Compiler) RegisterFormat(f *Format)

RegisterFormat registers custom format.

NOTE:

  • `regex` format can not be overridden
  • format assertions are disabled for draft >= 2019-09 see Compiler.AssertFormat

func (*Compiler) RegisterVocabulary

func (c *Compiler) RegisterVocabulary(vocab *Vocabulary)

RegisterVocabulary registers custom vocabulary.

func (*Compiler) UseLoader

func (c *Compiler) UseLoader(loader URLLoader)

UseLoader overrides the default URLLoader used to load schema resources.

func (*Compiler) UseRegexpEngine

func (c *Compiler) UseRegexpEngine(engine RegexpEngine)

UseRegexpEngine changes the regexp-engine used. By default it uses regexp package from go standard library.

NOTE: must be called before compiling any schemas.

type CompilerContext

type CompilerContext struct {
	// contains filtered or unexported fields
}

CompilerContext provides helpers for compiling a Vocabulary.

func (*CompilerContext) Enqueue

func (ctx *CompilerContext) Enqueue(schPath []string) *Schema

type Decoder

type Decoder struct {
	Name   string
	Decode func(string) ([]byte, error)
}

Decoder specifies how to decode specific contentEncoding.

type Draft

type Draft struct {
	// contains filtered or unexported fields
}

func (*Draft) String

func (d *Draft) String() string

type DuplicateAnchorError

type DuplicateAnchorError struct {
	Anchor string
	URL    string
	Ptr1   string
	Ptr2   string
}

func (*DuplicateAnchorError) Error

func (e *DuplicateAnchorError) Error() string

type DuplicateIDError

type DuplicateIDError struct {
	ID   string
	URL  string
	Ptr1 string
	Ptr2 string
}

func (*DuplicateIDError) Error

func (e *DuplicateIDError) Error() string

type DynamicRef

type DynamicRef struct {
	Ref    *Schema
	Anchor string // "" if not specified
}

type Enum

type Enum struct {
	Values []any
	// contains filtered or unexported fields
}

type ErrorKind

type ErrorKind interface {
	KeywordPath() []string
	LocalizedString(*message.Printer) string
}

type FileLoader

type FileLoader struct{}

func (FileLoader) Load

func (l FileLoader) Load(url string) (any, error)

func (FileLoader) ToFile

func (l FileLoader) ToFile(url string) (string, error)

type FlagOutput

type FlagOutput struct {
	Valid bool `json:"valid"`
}

Flag is output format with simple boolean property valid.

type Format

type Format struct {
	Name string

	// Validate checks if given value is of this format.
	Validate func(v any) error
}

Format defined specific format.

type InvalidJsonPointerError

type InvalidJsonPointerError struct {
	URL string
}

func (*InvalidJsonPointerError) Error

func (e *InvalidJsonPointerError) Error() string

type InvalidMetaSchemaURLError

type InvalidMetaSchemaURLError struct {
	URL string
	Err error
}

func (*InvalidMetaSchemaURLError) Error

func (e *InvalidMetaSchemaURLError) Error() string

type InvalidRegexError

type InvalidRegexError struct {
	URL   string
	Regex string
	Err   error
}

func (*InvalidRegexError) Error

func (e *InvalidRegexError) Error() string

type JSONPointerNotFoundError

type JSONPointerNotFoundError struct {
	URL string
}

func (*JSONPointerNotFoundError) Error

func (e *JSONPointerNotFoundError) Error() string

type LoadURLError

type LoadURLError struct {
	URL string
	Err error
}

func (*LoadURLError) Error

func (e *LoadURLError) Error() string

type MediaType

type MediaType struct {
	Name string

	// Validate checks whether bytes conform to this mediatype.
	Validate func([]byte) error

	// UnmarshalJSON unmarshals bytes into json value.
	// This must be nil if this mediatype is not compatible
	// with json.
	UnmarshalJSON func([]byte) (any, error)
}

MediaType specified how to validate bytes against specific contentMediaType.

type MetaSchemaCycleError

type MetaSchemaCycleError struct {
	URL string
}

func (*MetaSchemaCycleError) Error

func (e *MetaSchemaCycleError) Error() string

type MetaSchemaMismatchError

type MetaSchemaMismatchError struct {
	URL string
}

func (*MetaSchemaMismatchError) Error

func (e *MetaSchemaMismatchError) Error() string

type OutputError

type OutputError struct {
	Kind ErrorKind
	// contains filtered or unexported fields
}

func (OutputError) MarshalJSON

func (k OutputError) MarshalJSON() ([]byte, error)

type OutputUnit

type OutputUnit struct {
	Valid                   bool         `json:"valid"`
	KeywordLocation         string       `json:"keywordLocation"`
	AbsoluteKeywordLocation string       `json:"AbsoluteKeywordLocation,omitempty"`
	InstanceLocation        string       `json:"instanceLocation"`
	Error                   *OutputError `json:"error,omitempty"`
	Errors                  []OutputUnit `json:"errors,omitempty"`
}

type ParseAnchorError

type ParseAnchorError struct {
	URL string
}

func (*ParseAnchorError) Error

func (e *ParseAnchorError) Error() string

type ParseIDError

type ParseIDError struct {
	URL string
}

func (*ParseIDError) Error

func (e *ParseIDError) Error() string

type ParseURLError

type ParseURLError struct {
	URL string
	Err error
}

func (*ParseURLError) Error

func (e *ParseURLError) Error() string

type Position

type Position uint
const (
	PosProp Position = 0
	PosItem Position = 1
)

type Regexp

type Regexp interface {
	fmt.Stringer
	MatchString(string) bool
}

type RegexpEngine

type RegexpEngine func(string) (Regexp, error)

type Schema

type Schema struct {
	DraftVersion int
	Location     string

	// type agnostic --
	Bool            *bool // boolean schema
	ID              string
	Ref             *Schema
	Anchor          string
	RecusiveRef     *Schema
	RecursiveAnchor bool
	DynamicRef      *DynamicRef
	DynamicAnchor   string // "" if not specified
	Types           *Types
	Enum            *Enum
	Const           *any
	Not             *Schema
	AllOf           []*Schema
	AnyOf           []*Schema
	OneOf           []*Schema
	If              *Schema
	Then            *Schema
	Else            *Schema
	Format          *Format

	// object --
	MaxProperties         *int
	MinProperties         *int
	Required              []string
	PropertyNames         *Schema
	Properties            map[string]*Schema
	PatternProperties     map[Regexp]*Schema
	AdditionalProperties  any            // nil or bool or *Schema
	Dependencies          map[string]any // value is []string or *Schema
	DependentRequired     map[string][]string
	DependentSchemas      map[string]*Schema
	UnevaluatedProperties *Schema

	// array --
	MinItems         *int
	MaxItems         *int
	UniqueItems      bool
	Contains         *Schema
	MinContains      *int
	MaxContains      *int
	Items            any // nil or []*Schema or *Schema
	AdditionalItems  any // nil or bool or *Schema
	PrefixItems      []*Schema
	Items2020        *Schema
	UnevaluatedItems *Schema

	// string --
	MinLength        *int
	MaxLength        *int
	Pattern          Regexp
	ContentEncoding  *Decoder
	ContentMediaType *MediaType
	ContentSchema    *Schema

	// number --
	Maximum          *big.Rat
	Minimum          *big.Rat
	ExclusiveMaximum *big.Rat
	ExclusiveMinimum *big.Rat
	MultipleOf       *big.Rat

	Extensions []SchemaExt

	// annotations --
	Title       string
	Description string
	Default     *any
	Comment     string
	ReadOnly    bool
	WriteOnly   bool
	Examples    []any
	// contains filtered or unexported fields
}

func (*Schema) Validate

func (sch *Schema) Validate(v any) error

type SchemaExt

type SchemaExt interface {
	// Validate validates v against and errors if any are reported
	// to ctx.
	Validate(ctx *ValidatorContext, v any)
}

SchemaExt is compled form of vocabulary.

type SchemaPosition

type SchemaPosition []Position

type SchemaValidationError

type SchemaValidationError struct {
	URL string
	Err error
}

func (*SchemaValidationError) Error

func (e *SchemaValidationError) Error() string

type SchemeURLLoader

type SchemeURLLoader map[string]URLLoader

SchemeURLLoader delegates to other [URLLoaders] based on url scheme.

func (SchemeURLLoader) Load

func (l SchemeURLLoader) Load(url string) (any, error)

type Subschemas

type Subschemas map[string][]SchemaPosition

type Types

type Types int

func (Types) IsEmpty

func (tt Types) IsEmpty() bool

func (Types) String

func (tt Types) String() string

func (Types) ToStrings

func (tt Types) ToStrings() []string

type URLLoader

type URLLoader interface {
	// Load loads json from given absolute url.
	Load(url string) (any, error)
}

URLLoader knows how to load json from given url.

type UnsupportedDraftError

type UnsupportedDraftError struct {
	URL string
}

func (*UnsupportedDraftError) Error

func (e *UnsupportedDraftError) Error() string

type UnsupportedURLSchemeError

type UnsupportedURLSchemeError struct {
	// contains filtered or unexported fields
}

func (*UnsupportedURLSchemeError) Error

func (e *UnsupportedURLSchemeError) Error() string

type UnsupportedVocabularyError

type UnsupportedVocabularyError struct {
	URL        string
	Vocabulary string
}

func (*UnsupportedVocabularyError) Error

type ValidationError

type ValidationError struct {
	// absolute, dereferenced schema location.
	SchemaURL string

	// location of the JSON value within the instance being validated.
	InstanceLocation []string

	// kind of error
	ErrorKind ErrorKind

	// holds nested errors
	Causes []*ValidationError
}

func (*ValidationError) BasicOutput

func (e *ValidationError) BasicOutput() *OutputUnit

The `Basic` structure, a flat list of output units.

func (*ValidationError) DetailedOutput

func (e *ValidationError) DetailedOutput() *OutputUnit

The `Detailed` structure, based on the schema.

func (*ValidationError) Error

func (e *ValidationError) Error() string

func (*ValidationError) FlagOutput

func (e *ValidationError) FlagOutput() *FlagOutput

The `Flag` output format, merely the boolean result.

func (*ValidationError) GoString

func (e *ValidationError) GoString() string

func (*ValidationError) LocalizedBasicOutput

func (e *ValidationError) LocalizedBasicOutput(p *message.Printer) *OutputUnit

func (*ValidationError) LocalizedDetailedOutput

func (e *ValidationError) LocalizedDetailedOutput(p *message.Printer) *OutputUnit

func (*ValidationError) LocalizedError

func (e *ValidationError) LocalizedError(p *message.Printer) string

func (*ValidationError) LocalizedGoString

func (e *ValidationError) LocalizedGoString(p *message.Printer) string

type ValidatorContext

type ValidatorContext struct {
	// contains filtered or unexported fields
}

ValidatorContext provides helpers for validating with SchemaExt.

func (*ValidatorContext) AddErr

func (ctx *ValidatorContext) AddErr(err error)

AddErr reports the given err. This is typically used to report the error created by subschema validation.

NOTE that err must be of type *ValidationError.

func (*ValidatorContext) AddError

func (ctx *ValidatorContext) AddError(k ErrorKind)

AddError reports validation-error of given kind.

func (*ValidatorContext) AddErrors

func (ctx *ValidatorContext) AddErrors(errors []*ValidationError, k ErrorKind)

AddErrors reports validation-errors of given kind.

func (*ValidatorContext) Duplicates

func (ctx *ValidatorContext) Duplicates(arr []any) (int, int, error)

func (*ValidatorContext) Equals

func (ctx *ValidatorContext) Equals(v1, v2 any) (bool, error)

func (*ValidatorContext) EvaluatedItem

func (ctx *ValidatorContext) EvaluatedItem(index int)

EvaluatedItem marks items at given index of current array as evaluated.

func (*ValidatorContext) EvaluatedProp

func (ctx *ValidatorContext) EvaluatedProp(pname string)

EvaluatedProp marks given property of current object as evaluated.

func (*ValidatorContext) Validate

func (ctx *ValidatorContext) Validate(sch *Schema, v any, vpath []string) error

Validate validates v with sch. vpath gives path of v from current context value.

type Vocabulary

type Vocabulary struct {
	// URL identifier for this Vocabulary.
	URL string

	// Schema that is used to validate the keywords that is introduced by this
	// vocabulary.
	Schema *Schema

	// Subschemas lists the possible locations of subschemas introduced by
	// this vocabulary.
	Subschemas Subschemas

	// Compile compiles the keywords(introduced by this vocabulary) in obj into [SchemaExt].
	// If obj does not contain any keywords introduced by this vocabulary, nil SchemaExt must
	// be returned.
	Compile func(ctx *CompilerContext, obj map[string]any) (SchemaExt, error)
}

Vocabulary defines a set of keywords, their syntax and their semantics.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL