• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..15-Nov-2019-

.gitignoreH A D15-Nov-201925 43

.travis.ymlH A D15-Nov-2019177 87

README.mdH A D15-Nov-201910.5 KiB352261

errors.goH A D15-Nov-20197.1 KiB325240

format_checkers.goH A D15-Nov-20197 KiB251151

glide.yamlH A D15-Nov-2019282 1410

internalLog.goH A D15-Nov-20191.1 KiB388

jsonContext.goH A D15-Nov-20192 KiB7334

jsonLoader.goH A D15-Nov-20198.4 KiB365236

locales.goH A D15-Nov-20198.2 KiB314223

result.goH A D15-Nov-20195.4 KiB196125

schema.goH A D15-Nov-201926.9 KiB1,035870

schemaPool.goH A D15-Nov-20195.6 KiB193116

schemaReferencePool.goH A D15-Nov-20191.7 KiB6932

schemaType.goH A D15-Nov-20192.1 KiB8439

subSchema.goH A D15-Nov-20196.3 KiB256172

types.goH A D15-Nov-20191.4 KiB5929

utils.goH A D15-Nov-20194.6 KiB227134

validation.goH A D15-Nov-201923.6 KiB931704

README.md

1[![GoDoc](https://godoc.org/github.com/xeipuuv/gojsonschema?status.svg)](https://godoc.org/github.com/xeipuuv/gojsonschema)
2[![Build Status](https://travis-ci.org/xeipuuv/gojsonschema.svg)](https://travis-ci.org/xeipuuv/gojsonschema)
3
4# gojsonschema
5
6## Description
7
8An implementation of JSON Schema for the Go  programming language. Supports draft-04, draft-06 and draft-07.
9
10References :
11
12* http://json-schema.org
13* http://json-schema.org/latest/json-schema-core.html
14* http://json-schema.org/latest/json-schema-validation.html
15
16## Installation
17
18```
19go get github.com/xeipuuv/gojsonschema
20```
21
22Dependencies :
23* [github.com/xeipuuv/gojsonpointer](https://github.com/xeipuuv/gojsonpointer)
24* [github.com/xeipuuv/gojsonreference](https://github.com/xeipuuv/gojsonreference)
25* [github.com/stretchr/testify/assert](https://github.com/stretchr/testify#assert-package)
26
27## Usage
28
29### Example
30
31```go
32
33package main
34
35import (
36    "fmt"
37    "github.com/xeipuuv/gojsonschema"
38)
39
40func main() {
41
42    schemaLoader := gojsonschema.NewReferenceLoader("file:///home/me/schema.json")
43    documentLoader := gojsonschema.NewReferenceLoader("file:///home/me/document.json")
44
45    result, err := gojsonschema.Validate(schemaLoader, documentLoader)
46    if err != nil {
47        panic(err.Error())
48    }
49
50    if result.Valid() {
51        fmt.Printf("The document is valid\n")
52    } else {
53        fmt.Printf("The document is not valid. see errors :\n")
54        for _, desc := range result.Errors() {
55            fmt.Printf("- %s\n", desc)
56        }
57    }
58
59}
60
61
62```
63
64#### Loaders
65
66There are various ways to load your JSON data.
67In order to load your schemas and documents,
68first declare an appropriate loader :
69
70* Web / HTTP, using a reference :
71
72```go
73loader := gojsonschema.NewReferenceLoader("http://www.some_host.com/schema.json")
74```
75
76* Local file, using a reference :
77
78```go
79loader := gojsonschema.NewReferenceLoader("file:///home/me/schema.json")
80```
81
82References use the URI scheme, the prefix (file://) and a full path to the file are required.
83
84* JSON strings :
85
86```go
87loader := gojsonschema.NewStringLoader(`{"type": "string"}`)
88```
89
90* Custom Go types :
91
92```go
93m := map[string]interface{}{"type": "string"}
94loader := gojsonschema.NewGoLoader(m)
95```
96
97And
98
99```go
100type Root struct {
101	Users []User `json:"users"`
102}
103
104type User struct {
105	Name string `json:"name"`
106}
107
108...
109
110data := Root{}
111data.Users = append(data.Users, User{"John"})
112data.Users = append(data.Users, User{"Sophia"})
113data.Users = append(data.Users, User{"Bill"})
114
115loader := gojsonschema.NewGoLoader(data)
116```
117
118#### Validation
119
120Once the loaders are set, validation is easy :
121
122```go
123result, err := gojsonschema.Validate(schemaLoader, documentLoader)
124```
125
126Alternatively, you might want to load a schema only once and process to multiple validations :
127
128```go
129schema, err := gojsonschema.NewSchema(schemaLoader)
130...
131result1, err := schema.Validate(documentLoader1)
132...
133result2, err := schema.Validate(documentLoader2)
134...
135// etc ...
136```
137
138To check the result :
139
140```go
141    if result.Valid() {
142    	fmt.Printf("The document is valid\n")
143    } else {
144        fmt.Printf("The document is not valid. see errors :\n")
145        for _, err := range result.Errors() {
146        	// Err implements the ResultError interface
147            fmt.Printf("- %s\n", err)
148        }
149    }
150```
151
152## Working with Errors
153
154The library handles string error codes which you can customize by creating your own gojsonschema.locale and setting it
155```go
156gojsonschema.Locale = YourCustomLocale{}
157```
158
159However, each error contains additional contextual information.
160
161Newer versions of `gojsonschema` may have new additional errors, so code that uses a custom locale will need to be updated when this happens.
162
163**err.Type()**: *string* Returns the "type" of error that occurred. Note you can also type check. See below
164
165Note: An error of RequiredType has an err.Type() return value of "required"
166
167    "required": RequiredError
168    "invalid_type": InvalidTypeError
169    "number_any_of": NumberAnyOfError
170    "number_one_of": NumberOneOfError
171    "number_all_of": NumberAllOfError
172    "number_not": NumberNotError
173    "missing_dependency": MissingDependencyError
174    "internal": InternalError
175    "const": ConstEror
176    "enum": EnumError
177    "array_no_additional_items": ArrayNoAdditionalItemsError
178    "array_min_items": ArrayMinItemsError
179    "array_max_items": ArrayMaxItemsError
180    "unique": ItemsMustBeUniqueError
181    "contains" : ArrayContainsError
182    "array_min_properties": ArrayMinPropertiesError
183    "array_max_properties": ArrayMaxPropertiesError
184    "additional_property_not_allowed": AdditionalPropertyNotAllowedError
185    "invalid_property_pattern": InvalidPropertyPatternError
186    "invalid_property_name":  InvalidPropertyNameError
187    "string_gte": StringLengthGTEError
188    "string_lte": StringLengthLTEError
189    "pattern": DoesNotMatchPatternError
190    "multiple_of": MultipleOfError
191    "number_gte": NumberGTEError
192    "number_gt": NumberGTError
193    "number_lte": NumberLTEError
194    "number_lt": NumberLTError
195
196**err.Value()**: *interface{}* Returns the value given
197
198**err.Context()**: *gojsonschema.JsonContext* Returns the context. This has a String() method that will print something like this: (root).firstName
199
200**err.Field()**: *string* Returns the fieldname in the format firstName, or for embedded properties, person.firstName. This returns the same as the String() method on *err.Context()* but removes the (root). prefix.
201
202**err.Description()**: *string* The error description. This is based on the locale you are using. See the beginning of this section for overwriting the locale with a custom implementation.
203
204**err.DescriptionFormat()**: *string* The error description format. This is relevant if you are adding custom validation errors afterwards to the result.
205
206**err.Details()**: *gojsonschema.ErrorDetails* Returns a map[string]interface{} of additional error details specific to the error. For example, GTE errors will have a "min" value, LTE will have a "max" value. See errors.go for a full description of all the error details. Every error always contains a "field" key that holds the value of *err.Field()*
207
208Note in most cases, the err.Details() will be used to generate replacement strings in your locales, and not used directly. These strings follow the text/template format i.e.
209```
210{{.field}} must be greater than or equal to {{.min}}
211```
212
213The library allows you to specify custom template functions, should you require more complex error message handling.
214```go
215gojsonschema.ErrorTemplateFuncs = map[string]interface{}{
216	"allcaps": func(s string) string {
217		return strings.ToUpper(s)
218	},
219}
220```
221
222Given the above definition, you can use the custom function `"allcaps"` in your localization templates:
223```
224{{allcaps .field}} must be greater than or equal to {{.min}}
225```
226
227The above error message would then be rendered with the `field` value in capital letters. For example:
228```
229"PASSWORD must be greater than or equal to 8"
230```
231
232Learn more about what types of template functions you can use in `ErrorTemplateFuncs` by referring to Go's [text/template FuncMap](https://golang.org/pkg/text/template/#FuncMap) type.
233
234## Formats
235JSON Schema allows for optional "format" property to validate instances against well-known formats. gojsonschema ships with all of the formats defined in the spec that you can use like this:
236````json
237{"type": "string", "format": "email"}
238````
239Available formats: date-time, hostname, email, ipv4, ipv6, uri, uri-reference, uuid, regex. Some of the new formats in draft-06 and draft-07 are not yet implemented.
240
241For repetitive or more complex formats, you can create custom format checkers and add them to gojsonschema like this:
242
243```go
244// Define the format checker
245type RoleFormatChecker struct {}
246
247// Ensure it meets the gojsonschema.FormatChecker interface
248func (f RoleFormatChecker) IsFormat(input interface{}) bool {
249
250    asString, ok := input.(string)
251    if ok == false {
252        return false
253    }
254
255    return strings.HasPrefix("ROLE_", asString)
256}
257
258// Add it to the library
259gojsonschema.FormatCheckers.Add("role", RoleFormatChecker{})
260````
261
262Now to use in your json schema:
263````json
264{"type": "string", "format": "role"}
265````
266
267Another example would be to check if the provided integer matches an id on database:
268
269JSON schema:
270```json
271{"type": "integer", "format": "ValidUserId"}
272```
273
274```go
275// Define the format checker
276type ValidUserIdFormatChecker struct {}
277
278// Ensure it meets the gojsonschema.FormatChecker interface
279func (f ValidUserIdFormatChecker) IsFormat(input interface{}) bool {
280
281    asFloat64, ok := input.(float64) // Numbers are always float64 here
282    if ok == false {
283        return false
284    }
285
286    // XXX
287    // do the magic on the database looking for the int(asFloat64)
288
289    return true
290}
291
292// Add it to the library
293gojsonschema.FormatCheckers.Add("ValidUserId", ValidUserIdFormatChecker{})
294````
295
296## Additional custom validation
297After the validation has run and you have the results, you may add additional
298errors using `Result.AddError`. This is useful to maintain the same format within the resultset instead
299of having to add special exceptions for your own errors. Below is an example.
300
301```go
302type AnswerInvalidError struct {
303    gojsonschema.ResultErrorFields
304}
305
306func newAnswerInvalidError(context *gojsonschema.JsonContext, value interface{}, details gojsonschema.ErrorDetails) *AnswerInvalidError {
307    err := AnswerInvalidError{}
308    err.SetContext(context)
309    err.SetType("custom_invalid_error")
310    // it is important to use SetDescriptionFormat() as this is used to call SetDescription() after it has been parsed
311    // using the description of err will be overridden by this.
312    err.SetDescriptionFormat("Answer to the Ultimate Question of Life, the Universe, and Everything is {{.answer}}")
313    err.SetValue(value)
314    err.SetDetails(details)
315
316    return &err
317}
318
319func main() {
320    // ...
321    schema, err := gojsonschema.NewSchema(schemaLoader)
322    result, err := gojsonschema.Validate(schemaLoader, documentLoader)
323
324    if true { // some validation
325        jsonContext := gojsonschema.NewJsonContext("question", nil)
326        errDetail := gojsonschema.ErrorDetails{
327            "answer": 42,
328        }
329        result.AddError(
330            newAnswerInvalidError(
331                gojsonschema.NewJsonContext("answer", jsonContext),
332                52,
333                errDetail,
334            ),
335            errDetail,
336        )
337    }
338
339    return result, err
340
341}
342```
343
344This is especially useful if you want to add validation beyond what the
345json schema drafts can provide such business specific logic.
346
347## Uses
348
349gojsonschema uses the following test suite :
350
351https://github.com/json-schema/JSON-Schema-Test-Suite
352