golang implementation of https://json-schema.org drafts 7 & 2019-09
Go
480
68 commits
updated Dec 18, 2024
golang implementation of the JSON Schema Specification, which lets you write JSON that validates some other json. Rad.
We would love involvement from more people! If you notice any errors or would like to submit changes, please see our Contributing Guidelines.
We’ve set up a separate document for developer guidelines!
Here’s a quick example pulled from the godoc:
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/qri-io/jsonschema"
)
func main() {
ctx := context.Background()
var schemaData = []byte(`{
"$id": "https://qri.io/schema/",
"$comment" : "sample comment",
"title": "Person",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
},
"friends": {
"type" : "array",
"items" : { "title" : "REFERENCE", "$ref" : "#" }
}
},
"required": ["firstName", "lastName"]
}`)
rs := &jsonschema.Schema{}
if err := json.Unmarshal(schemaData, rs); err != nil {
panic("unmarshal schema: " + err.Error())
}
var valid = []byte(`{
"firstName" : "George",
"lastName" : "Michael"
}`)
errs, err := rs.ValidateBytes(ctx, valid)
if err != nil {
panic(err)
}
if len(errs) > 0 {
fmt.Println(errs[0].Error())
}
var invalidPerson = []byte(`{
"firstName" : "Prince"
}`)
errs, err = rs.ValidateBytes(ctx, invalidPerson)
if err != nil {
panic(err)
}
if len(errs) > 0 {
fmt.Println(errs[0].Error())
}
var invalidFriend = []byte(`{
"firstName" : "Jay",
"lastName" : "Z",
"friends" : [{
"firstName" : "Nas"
}]
}`)
errs, err = rs.ValidateBytes(ctx, invalidFriend)
if err != nil {
panic(err)
}
if len(errs) > 0 {
fmt.Println(errs[0].Error())
}
}
// Output:
// /: {"firstName":"Prince... "lastName" value is required
// /friends/0: {"firstName":"Nas"} "lastName" value is required
The godoc gives an example of how to supply your own validators to extend the standard keywords supported by the spec.
It involves three steps that should happen before allocating any Schema instances that use the validator:
Keyword interfacedraft2019_09_keywords.go)KeyMaker function.package main
import (
"context"
"encoding/json"
"fmt"
jptr "github.com/qri-io/jsonpointer"
"github.com/qri-io/jsonschema"
)
// your custom validator
type IsFoo bool
// newIsFoo is a jsonschama.KeyMaker
func newIsFoo() jsonschema.Keyword {
return new(IsFoo)
}
// Validate implements jsonschema.Keyword
func (f *IsFoo) Validate(propPath string, data interface{}, errs *[]jsonschema.KeyError) {}
// Register implements jsonschema.Keyword
func (f *IsFoo) Register(uri string, registry *jsonschema.SchemaRegistry) {}
// Resolve implements jsonschema.Keyword
func (f *IsFoo) Resolve(pointer jptr.Pointer, uri string) *jsonschema.Schema {
return nil
}
// ValidateKeyword implements jsonschema.Keyword
func (f *IsFoo) ValidateKeyword(ctx context.Context, currentState *jsonschema.ValidationState, data interface{}) {
if str, ok := data.(string); ok {
if str != "foo" {
currentState.AddError(data, fmt.Sprintf("should be foo. plz make '%s' == foo. plz", str))
}
}
}
func main() {
// register a custom validator by supplying a function
// that creates new instances of your Validator.
jsonschema.RegisterKeyword("foo", newIsFoo)
// If you register a custom validator, you'll need to manually register
// any other JSON Schema validators you need.
jsonschema.LoadDraft2019_09()
schBytes := []byte(`{ "foo": true }`)
rs := new(jsonschema.Schema)
if err := json.Unmarshal(schBytes, rs); err != nil {
// Real programs handle errors.
panic(err)
}
errs, err := rs.ValidateBytes(context.Background(), []byte(`"bar"`))
if err != nil {
panic(err)
}
fmt.Println(errs[0].Error())
// Output: /: "bar" should be foo. plz make 'bar' == foo. plz
}
Overall
Maintained
Code review
Go module
Latest release
Releases this year
1,190 followers · starred Feb 2020
1,319 followers · starred Mar 2020
3,989 followers · starred Oct 2022
345 followers · starred Oct 2018
golang implementation of https://json-schema.org drafts 7 & 2019-09
Go
480
68 commits
updated Dec 18, 2024
golang implementation of the JSON Schema Specification, which lets you write JSON that validates some other json. Rad.
We would love involvement from more people! If you notice any errors or would like to submit changes, please see our Contributing Guidelines.
We’ve set up a separate document for developer guidelines!
Here’s a quick example pulled from the godoc:
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/qri-io/jsonschema"
)
func main() {
ctx := context.Background()
var schemaData = []byte(`{
"$id": "https://qri.io/schema/",
"$comment" : "sample comment",
"title": "Person",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
},
"friends": {
"type" : "array",
"items" : { "title" : "REFERENCE", "$ref" : "#" }
}
},
"required": ["firstName", "lastName"]
}`)
rs := &jsonschema.Schema{}
if err := json.Unmarshal(schemaData, rs); err != nil {
panic("unmarshal schema: " + err.Error())
}
var valid = []byte(`{
"firstName" : "George",
"lastName" : "Michael"
}`)
errs, err := rs.ValidateBytes(ctx, valid)
if err != nil {
panic(err)
}
if len(errs) > 0 {
fmt.Println(errs[0].Error())
}
var invalidPerson = []byte(`{
"firstName" : "Prince"
}`)
errs, err = rs.ValidateBytes(ctx, invalidPerson)
if err != nil {
panic(err)
}
if len(errs) > 0 {
fmt.Println(errs[0].Error())
}
var invalidFriend = []byte(`{
"firstName" : "Jay",
"lastName" : "Z",
"friends" : [{
"firstName" : "Nas"
}]
}`)
errs, err = rs.ValidateBytes(ctx, invalidFriend)
if err != nil {
panic(err)
}
if len(errs) > 0 {
fmt.Println(errs[0].Error())
}
}
// Output:
// /: {"firstName":"Prince... "lastName" value is required
// /friends/0: {"firstName":"Nas"} "lastName" value is required
The godoc gives an example of how to supply your own validators to extend the standard keywords supported by the spec.
It involves three steps that should happen before allocating any Schema instances that use the validator:
Keyword interfacedraft2019_09_keywords.go)KeyMaker function.package main
import (
"context"
"encoding/json"
"fmt"
jptr "github.com/qri-io/jsonpointer"
"github.com/qri-io/jsonschema"
)
// your custom validator
type IsFoo bool
// newIsFoo is a jsonschama.KeyMaker
func newIsFoo() jsonschema.Keyword {
return new(IsFoo)
}
// Validate implements jsonschema.Keyword
func (f *IsFoo) Validate(propPath string, data interface{}, errs *[]jsonschema.KeyError) {}
// Register implements jsonschema.Keyword
func (f *IsFoo) Register(uri string, registry *jsonschema.SchemaRegistry) {}
// Resolve implements jsonschema.Keyword
func (f *IsFoo) Resolve(pointer jptr.Pointer, uri string) *jsonschema.Schema {
return nil
}
// ValidateKeyword implements jsonschema.Keyword
func (f *IsFoo) ValidateKeyword(ctx context.Context, currentState *jsonschema.ValidationState, data interface{}) {
if str, ok := data.(string); ok {
if str != "foo" {
currentState.AddError(data, fmt.Sprintf("should be foo. plz make '%s' == foo. plz", str))
}
}
}
func main() {
// register a custom validator by supplying a function
// that creates new instances of your Validator.
jsonschema.RegisterKeyword("foo", newIsFoo)
// If you register a custom validator, you'll need to manually register
// any other JSON Schema validators you need.
jsonschema.LoadDraft2019_09()
schBytes := []byte(`{ "foo": true }`)
rs := new(jsonschema.Schema)
if err := json.Unmarshal(schBytes, rs); err != nil {
// Real programs handle errors.
panic(err)
}
errs, err := rs.ValidateBytes(context.Background(), []byte(`"bar"`))
if err != nil {
panic(err)
}
fmt.Println(errs[0].Error())
// Output: /: "bar" should be foo. plz make 'bar' == foo. plz
}
Overall
Maintained
Code review
Go module
Latest release
Releases this year
1,190 followers · starred Feb 2020
1,319 followers · starred Mar 2020
3,989 followers · starred Oct 2022
345 followers · starred Oct 2018