golang implementation of the JSON Schema Specification, which lets you write JSON that validates some other json. Rad.
- Encode schemas back to JSON
- Supply Your own Custom Validators
- Uses Standard Go idioms
- Fastest Go implementation of JSON Schema validators (draft 7 only, benchmarks are here - thanks @TheWildBlue!)
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 (
"encoding/json"
"fmt"
"github.com/qri-io/jsonschema"
)
func main() {
var schemaData = []byte(`{
"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.RootSchema{}
if err := json.Unmarshal(schemaData, rs); err != nil {
panic("unmarshal schema: " + err.Error())
}
var valid = []byte(`{
"firstName" : "George",
"lastName" : "Michael"
}`)
if errors, _ := rs.ValidateBytes(valid); len(errors) > 0 {
panic(errors)
}
var invalidPerson = []byte(`{
"firstName" : "Prince"
}`)
if errors, _ := rs.ValidateBytes(invalidPerson); len(errors) > 0 {
fmt.Println(errors[0].Error())
}
var invalidFriend = []byte(`{
"firstName" : "Jay",
"lastName" : "Z",
"friends" : [{
"firstName" : "Nas"
}]
}`)
if errors, _ := rs.ValidateBytes(invalidFriend); len(errors) > 0 {
fmt.Println(errors[0].Error())
}
}
The godoc gives an example of how to supply your own validators to extend the standard keywords supported by the spec.
It involves two steps that should happen before allocating any RootSchema instances that use the validator:
- create a custom type that implements the
Validator
interface - call RegisterValidator with the keyword you'd like to detect in JSON, and a
ValMaker
function.
package main
import (
"encoding/json"
"fmt"
"github.com/qri-io/jsonschema"
)
// your custom validator
type IsFoo bool
// newIsFoo is a jsonschama.ValMaker
func newIsFoo() jsonschema.Validator {
return new(IsFoo)
}
// Validate implements jsonschema.Validator
func (f IsFoo) Validate(data interface{}) []jsonschema.ValError {
if str, ok := data.(string); ok {
if str != "foo" {
return []jsonschema.ValError{
{Message: fmt.Sprintf("'%s' is not foo. It should be foo. plz make '%s' == foo. plz", str, str)},
}
}
}
return nil
}
func main() {
// register a custom validator by supplying a function
// that creates new instances of your Validator.
jsonschema.RegisterValidator("foo", newIsFoo)
schBytes := []byte(`{ "foo": true }`)
// parse a schema that uses your custom keyword
rs := new(jsonschema.RootSchema)
if err := json.Unmarshal(schBytes, rs); err != nil {
// Real programs handle errors.
panic(err)
}
// validate some JSON
errors := rs.ValidateBytes([]byte(`"bar"`))
// print le error
fmt.Println(errs[0].Error())
// Output: 'bar' is not foo. It should be foo. plz make 'bar' == foo. plz
}