...
1# jsonschema
2[](https://qri.io)
3[](http://godoc.org/github.com/qri-io/jsonschema)
4[](./LICENSE)
5[](https://codecov.io/gh/qri-io/jsonschema)
6[](https://circleci.com/gh/qri-io/jsonschema)
7[](https://goreportcard.com/report/github.com/qri-io/jsonschema)
8
9golang implementation of the [JSON Schema Specification](http://json-schema.org/), which lets you write JSON that validates some other json. Rad.
10
11### Package Features
12
13* Encode schemas back to JSON
14* Supply Your own Custom Validators
15* Uses Standard Go idioms
16* Fastest Go implementation of [JSON Schema validators](http://json-schema.org/implementations.html#validators) (draft2019_9 only, (old - draft 7) benchmarks are [here](https://github.com/TheWildBlue/validator-benchmarks) - thanks [@TheWildBlue](https://github.com/TheWildBlue)!)
17
18### Getting Involved
19
20We would love involvement from more people! If you notice any errors or would
21like to submit changes, please see our
22[Contributing Guidelines](./.github/CONTRIBUTING.md).
23
24### Developing
25
26We've set up a separate document for [developer guidelines](https://github.com/qri-io/jsonschema/blob/master/DEVELOPERS.md)!
27
28## Basic Usage
29
30Here's a quick example pulled from the [godoc](https://godoc.org/github.com/qri-io/jsonschema):
31
32```go
33package main
34
35import (
36 "encoding/json"
37 "fmt"
38
39 "github.com/qri-io/jsonschema"
40)
41
42func main() {
43 var schemaData = []byte(`{
44 "$id": "https://qri.io/schema/",
45 "$comment" : "sample comment",
46 "title": "Person",
47 "type": "object",
48 "properties": {
49 "firstName": {
50 "type": "string"
51 },
52 "lastName": {
53 "type": "string"
54 },
55 "age": {
56 "description": "Age in years",
57 "type": "integer",
58 "minimum": 0
59 },
60 "friends": {
61 "type" : "array",
62 "items" : { "title" : "REFERENCE", "$ref" : "#" }
63 }
64 },
65 "required": ["firstName", "lastName"]
66 }`)
67
68 rs := &Schema{}
69 if err := json.Unmarshal(schemaData, rs); err != nil {
70 panic("unmarshal schema: " + err.Error())
71 }
72
73 var valid = []byte(`{
74 "firstName" : "George",
75 "lastName" : "Michael"
76 }`)
77 errs, err := rs.ValidateBytes(valid)
78 if err != nil {
79 panic(err)
80 }
81
82 if len(errs) > 0 {
83 fmt.Println(errs[0].Error())
84 }
85
86 var invalidPerson = []byte(`{
87 "firstName" : "Prince"
88 }`)
89
90 errs, err = rs.ValidateBytes(invalidPerson)
91 if err != nil {
92 panic(err)
93 }
94 if len(errs) > 0 {
95 fmt.Println(errs[0].Error())
96 }
97
98 var invalidFriend = []byte(`{
99 "firstName" : "Jay",
100 "lastName" : "Z",
101 "friends" : [{
102 "firstName" : "Nas"
103 }]
104 }`)
105 errs, err = rs.ValidateBytes(invalidFriend)
106 if err != nil {
107 panic(err)
108 }
109 if len(errs) > 0 {
110 fmt.Println(errs[0].Error())
111 }
112}
113```
114
115## Custom Keywords
116
117The [godoc](https://godoc.org/github.com/qri-io/jsonschema) gives an example of how to supply your own validators to extend the standard keywords supported by the spec.
118
119It involves three steps that should happen _before_ allocating any Schema instances that use the validator:
1201. create a custom type that implements the `Keyword` interface
1212. Load the appropriate draft keyword set (see `draft2019_09_keywords.go`)
1223. call RegisterKeyword with the keyword you'd like to detect in JSON, and a `KeyMaker` function.
123
124
125```go
126package main
127
128import (
129 "encoding/json"
130 "fmt"
131
132 "github.com/qri-io/jsonschema"
133)
134
135// your custom validator
136type IsFoo bool
137
138// newIsFoo is a jsonschama.KeyMaker
139func newIsFoo() Keyword {
140 return new(IsFoo)
141}
142
143// Validate implements jsonschema.Keyword
144func (f *IsFoo) Validate(propPath string, data interface{}, errs *[]KeyError) {}
145
146// Register implements jsonschema.Keyword
147func (f *IsFoo) Register(uri string, registry *SchemaRegistry) {}
148
149// Resolve implements jsonschema.Keyword
150func (f *IsFoo) Resolve(pointer jptr.Pointer, uri string) *Schema {
151 return nil
152}
153
154// ValidateKeyword implements jsonschema.Keyword
155func (f *IsFoo) ValidateKeyword(ctx context.Context, currentState *ValidationState, data interface{}) {
156 if str, ok := data.(string); ok {
157 if str != "foo" {
158 currentState.AddError(data, fmt.Sprintf("should be foo. plz make '%s' == foo. plz", str))
159 }
160 }
161}
162
163func main() {
164 // register a custom validator by supplying a function
165 // that creates new instances of your Validator.
166 jsonschema.RegisterKeyword("foo", newIsFoo)
167
168 schBytes := []byte(`{ "foo": true }`)
169
170 rs := new(Schema)
171 if err := json.Unmarshal(schBytes, rs); err != nil {
172 // Real programs handle errors.
173 panic(err)
174 }
175
176 errs, err := rs.ValidateBytes([]byte(`"bar"`))
177 if err != nil {
178 panic(err)
179 }
180
181 fmt.Println(errs[0].Error())
182 // Output: /: "bar" should be foo. plz make 'bar' == foo. plz
183}
184```
185
View as plain text