在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:xeipuuv/gojsonschema开源软件地址:https://github.com/xeipuuv/gojsonschema开源编程语言:Go 100.0%开源软件介绍:gojsonschemaDescriptionAn implementation of JSON Schema for the Go programming language. Supports draft-04, draft-06 and draft-07. References :
Installation
Dependencies :
UsageExamplepackage main
import (
"fmt"
"github.com/xeipuuv/gojsonschema"
)
func main() {
schemaLoader := gojsonschema.NewReferenceLoader("file:///home/me/schema.json")
documentLoader := gojsonschema.NewReferenceLoader("file:///home/me/document.json")
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
if err != nil {
panic(err.Error())
}
if result.Valid() {
fmt.Printf("The document is valid\n")
} else {
fmt.Printf("The document is not valid. see errors :\n")
for _, desc := range result.Errors() {
fmt.Printf("- %s\n", desc)
}
}
}
LoadersThere are various ways to load your JSON data. In order to load your schemas and documents, first declare an appropriate loader :
loader := gojsonschema.NewReferenceLoader("http://www.some_host.com/schema.json")
loader := gojsonschema.NewReferenceLoader("file:///home/me/schema.json") References use the URI scheme, the prefix (file://) and a full path to the file are required.
loader := gojsonschema.NewStringLoader(`{"type": "string"}`)
m := map[string]interface{}{"type": "string"}
loader := gojsonschema.NewGoLoader(m) And type Root struct {
Users []User `json:"users"`
}
type User struct {
Name string `json:"name"`
}
...
data := Root{}
data.Users = append(data.Users, User{"John"})
data.Users = append(data.Users, User{"Sophia"})
data.Users = append(data.Users, User{"Bill"})
loader := gojsonschema.NewGoLoader(data) ValidationOnce the loaders are set, validation is easy : result, err := gojsonschema.Validate(schemaLoader, documentLoader) Alternatively, you might want to load a schema only once and process to multiple validations : schema, err := gojsonschema.NewSchema(schemaLoader)
...
result1, err := schema.Validate(documentLoader1)
...
result2, err := schema.Validate(documentLoader2)
...
// etc ... To check the result : if result.Valid() {
fmt.Printf("The document is valid\n")
} else {
fmt.Printf("The document is not valid. see errors :\n")
for _, err := range result.Errors() {
// Err implements the ResultError interface
fmt.Printf("- %s\n", err)
}
} Loading local schemasBy default sl := gojsonschema.NewSchemaLoader()
loader1 := gojsonschema.NewStringLoader(`{ "type" : "string" }`)
err := sl.AddSchema("http://some_host.com/string.json", loader1) Alternatively if your schema already has an loader2 := gojsonschema.NewStringLoader(`{
"$id" : "http://some_host.com/maxlength.json",
"maxLength" : 5
}`)
err = sl.AddSchemas(loader2) The main schema should be passed to the loader3 := gojsonschema.NewStringLoader(`{
"$id" : "http://some_host.com/main.json",
"allOf" : [
{ "$ref" : "http://some_host.com/string.json" },
{ "$ref" : "http://some_host.com/maxlength.json" }
]
}`)
schema, err := sl.Compile(loader3)
documentLoader := gojsonschema.NewStringLoader(`"hello world"`)
result, err := schema.Validate(documentLoader) It's also possible to pass a err = sl.AddSchemas(loader3)
schema, err := sl.Compile(gojsonschema.NewReferenceLoader("http://some_host.com/main.json")) Schemas added by Using a specific draftBy default Autodectection can be turned off with the sl := gojsonschema.NewSchemaLoader()
sl.Draft = gojsonschema.Draft7
sl.AutoDetect = false If autodetection is on (default), a draft-07 schema can savely reference draft-04 schemas and vice-versa, as long as Meta-schema validationSchemas that are added using the The following example will produce an error as sl := gojsonschema.NewSchemaLoader()
sl.Validate = true
err := sl.AddSchemas(gojsonschema.NewStringLoader(`{
"$id" : "http://some_host.com/invalid.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"multipleOf" : true
}`))
Errors returned by meta-schema validation are more readable and contain more information, which helps significantly if you are developing a schema. Meta-schema validation also works with a custom Working with ErrorsThe library handles string error codes which you can customize by creating your own gojsonschema.locale and setting it gojsonschema.Locale = YourCustomLocale{} However, each error contains additional contextual information. Newer versions of err.Type(): string Returns the "type" of error that occurred. Note you can also type check. See below Note: An error of RequiredType has an err.Type() return value of "required"
err.Value(): interface{} Returns the value given err.Context(): gojsonschema.JsonContext Returns the context. This has a String() method that will print something like this: (root).firstName 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. 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. err.DescriptionFormat(): string The error description format. This is relevant if you are adding custom validation errors afterwards to the result. 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() Note 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.
The library allows you to specify custom template functions, should you require more complex error message handling. gojsonschema.ErrorTemplateFuncs = map[string]interface{}{
"allcaps": func(s string) string {
return strings.ToUpper(s)
},
} Given the above definition, you can use the custom function
The above error message would then be rendered with the
Learn more about what types of template functions you can use in FormatsJSON 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: {"type": "string", "format": "email"} Not all formats defined in draft-07 are available. Implemented formats are:
The validation code for For repetitive or more complex formats, you can create custom format checkers and add them to gojsonschema like this: // Define the format checker
type RoleFormatChecker struct {}
// Ensure it meets the gojsonschema.FormatChecker interface
func (f RoleFormatChecker) IsFormat(input interface{}) bool {
asString, ok := input.(string)
if ok == false {
return false
}
return strings.HasPrefix("ROLE_", asString)
}
// Add it to the library
gojsonschema.FormatCheckers.Add("role", RoleFormatChecker{}) Now to use in your json schema: {"type": "string", "format": "role"} Another example would be to check if the provided integer matches an id on database: JSON schema: {"type": "integer", "format": "ValidUserId"} // Define the format checker
type ValidUserIdFormatChecker struct {}
// Ensure it meets the gojsonschema.FormatChecker interface
func (f ValidUserIdFormatChecker) IsFormat(input interface{}) bool {
asFloat64, ok := input.(float64) // Numbers are always float64 here
if ok == false {
return false
}
// XXX
// do the magic on the database looking for the int(asFloat64)
return true
}
// Add it to the library
gojsonschema.FormatCheckers.Add("ValidUserId", ValidUserIdFormatChecker{}) Formats can also be removed, for example if you want to override one of the formats that is defined by default. gojsonschema.FormatCheckers.Remove("hostname") Additional custom validationAfter the validation has run and you have the results, you may add additional
errors using type AnswerInvalidError struct {
gojsonschema.ResultErrorFields
}
func newAnswerInvalidError(context *gojsonschema.JsonContext, value interface{}, details gojsonschema.ErrorDetails) *AnswerInvalidError {
err := AnswerInvalidError{}
err.SetContext(context)
err.SetType("custom_invalid_error")
// it is important to use SetDescriptionFormat() as this is used to call SetDescription() after it has been parsed
// using the description of err will be overridden by this.
err.SetDescriptionFormat("Answer to the Ultimate Question of Life, the Universe, and Everything is {{.answer}}")
err.SetValue(value)
err.SetDetails(details)
return &err
}
func main() {
// ...
schema, err := gojsonschema.NewSchema(schemaLoader)
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
if true { // some validation
jsonContext := gojsonschema.NewJsonContext("question", nil)
errDetail := gojsonschema.ErrorDetails{
"answer": 42,
}
result.AddError(
newAnswerInvalidError(
gojsonschema.NewJsonContext("answer", jsonContext),
52,
errDetail,
),
errDetail,
)
}
return result, err
} This is especially useful if you want to add validation beyond what the json schema drafts can provide such business specific logic. Usesgojsonschema uses the following test suite : https://github.com/json-schema/JSON-Schema-Test-Suite |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论