mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-10 13:37:08 +08:00
Bump microsoft/hcsshim to v0.8.7
Signed-off-by: ulyssessouza <ulyssessouza@gmail.com>
This commit is contained in:
2
vendor/github.com/xeipuuv/gojsonschema/.gitignore
generated
vendored
2
vendor/github.com/xeipuuv/gojsonschema/.gitignore
generated
vendored
@ -1 +1,3 @@
|
||||
*.sw[nop]
|
||||
*.iml
|
||||
.vscode/
|
||||
|
6
vendor/github.com/xeipuuv/gojsonschema/.travis.yml
generated
vendored
6
vendor/github.com/xeipuuv/gojsonschema/.travis.yml
generated
vendored
@ -1,7 +1,7 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.3
|
||||
- 1.5
|
||||
before_install:
|
||||
- go get github.com/sigu-399/gojsonreference
|
||||
- go get github.com/sigu-399/gojsonpointer
|
||||
- go get github.com/xeipuuv/gojsonreference
|
||||
- go get github.com/xeipuuv/gojsonpointer
|
||||
- go get github.com/stretchr/testify/assert
|
||||
|
133
vendor/github.com/xeipuuv/gojsonschema/README.md
generated
vendored
133
vendor/github.com/xeipuuv/gojsonschema/README.md
generated
vendored
@ -1,10 +1,11 @@
|
||||
[](https://godoc.org/github.com/xeipuuv/gojsonschema)
|
||||
[](https://travis-ci.org/xeipuuv/gojsonschema)
|
||||
|
||||
# gojsonschema
|
||||
|
||||
## Description
|
||||
|
||||
An implementation of JSON Schema, based on IETF's draft v4 - Go language
|
||||
An implementation of JSON Schema for the Go programming language. Supports draft-04, draft-06 and draft-07.
|
||||
|
||||
References :
|
||||
|
||||
@ -155,7 +156,9 @@ The library handles string error codes which you can customize by creating your
|
||||
gojsonschema.Locale = YourCustomLocale{}
|
||||
```
|
||||
|
||||
However, each error contains additional contextual information.
|
||||
However, each error contains additional contextual information.
|
||||
|
||||
Newer versions of `gojsonschema` may have new additional errors, so code that uses a custom locale will need to be updated when this happens.
|
||||
|
||||
**err.Type()**: *string* Returns the "type" of error that occurred. Note you can also type check. See below
|
||||
|
||||
@ -169,15 +172,18 @@ Note: An error of RequiredType has an err.Type() return value of "required"
|
||||
"number_not": NumberNotError
|
||||
"missing_dependency": MissingDependencyError
|
||||
"internal": InternalError
|
||||
"const": ConstEror
|
||||
"enum": EnumError
|
||||
"array_no_additional_items": ArrayNoAdditionalItemsError
|
||||
"array_min_items": ArrayMinItemsError
|
||||
"array_max_items": ArrayMaxItemsError
|
||||
"unique": ItemsMustBeUniqueError
|
||||
"contains" : ArrayContainsError
|
||||
"array_min_properties": ArrayMinPropertiesError
|
||||
"array_max_properties": ArrayMaxPropertiesError
|
||||
"additional_property_not_allowed": AdditionalPropertyNotAllowedError
|
||||
"invalid_property_pattern": InvalidPropertyPatternError
|
||||
"invalid_property_name": InvalidPropertyNameError
|
||||
"string_gte": StringLengthGTEError
|
||||
"string_lte": StringLengthLTEError
|
||||
"pattern": DoesNotMatchPatternError
|
||||
@ -189,25 +195,48 @@ 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.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 i.e.
|
||||
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.
|
||||
```
|
||||
%field% must be greater than or equal to %min%
|
||||
{{.field}} must be greater than or equal to {{.min}}
|
||||
```
|
||||
|
||||
The library allows you to specify custom template functions, should you require more complex error message handling.
|
||||
```go
|
||||
gojsonschema.ErrorTemplateFuncs = map[string]interface{}{
|
||||
"allcaps": func(s string) string {
|
||||
return strings.ToUpper(s)
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Given the above definition, you can use the custom function `"allcaps"` in your localization templates:
|
||||
```
|
||||
{{allcaps .field}} must be greater than or equal to {{.min}}
|
||||
```
|
||||
|
||||
The above error message would then be rendered with the `field` value in capital letters. For example:
|
||||
```
|
||||
"PASSWORD must be greater than or equal to 8"
|
||||
```
|
||||
|
||||
Learn 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.
|
||||
|
||||
## Formats
|
||||
JSON Schema allows for optional "format" property to validate strings against well-known formats. gojsonschema ships with all of the formats defined in the spec that you can use like this:
|
||||
JSON 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:
|
||||
````json
|
||||
{"type": "string", "format": "email"}
|
||||
````
|
||||
Available formats: date-time, hostname, email, ipv4, ipv6, uri.
|
||||
Available 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.
|
||||
|
||||
For repetitive or more complex formats, you can create custom format checkers and add them to gojsonschema like this:
|
||||
|
||||
@ -216,8 +245,14 @@ For repetitive or more complex formats, you can create custom format checkers an
|
||||
type RoleFormatChecker struct {}
|
||||
|
||||
// Ensure it meets the gojsonschema.FormatChecker interface
|
||||
func (f RoleFormatChecker) IsFormat(input string) bool {
|
||||
return strings.HasPrefix("ROLE_", input)
|
||||
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
|
||||
@ -229,6 +264,86 @@ 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:
|
||||
```json
|
||||
{"type": "integer", "format": "ValidUserId"}
|
||||
```
|
||||
|
||||
```go
|
||||
// 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{})
|
||||
````
|
||||
|
||||
## Additional custom validation
|
||||
After the validation has run and you have the results, you may add additional
|
||||
errors using `Result.AddError`. This is useful to maintain the same format within the resultset instead
|
||||
of having to add special exceptions for your own errors. Below is an example.
|
||||
|
||||
```go
|
||||
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.
|
||||
|
||||
## Uses
|
||||
|
||||
gojsonschema uses the following test suite :
|
||||
|
106
vendor/github.com/xeipuuv/gojsonschema/errors.go
generated
vendored
106
vendor/github.com/xeipuuv/gojsonschema/errors.go
generated
vendored
@ -1,10 +1,20 @@
|
||||
package gojsonschema
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"bytes"
|
||||
"sync"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var errorTemplates errorTemplate = errorTemplate{template.New("errors-new"), sync.RWMutex{}}
|
||||
|
||||
// template.Template is not thread-safe for writing, so some locking is done
|
||||
// sync.RWMutex is used for efficiently locking when new templates are created
|
||||
type errorTemplate struct {
|
||||
*template.Template
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
type (
|
||||
// RequiredError. ErrorDetails: property string
|
||||
RequiredError struct {
|
||||
@ -46,6 +56,11 @@ type (
|
||||
ResultErrorFields
|
||||
}
|
||||
|
||||
// ConstError. ErrorDetails: allowed
|
||||
ConstError struct {
|
||||
ResultErrorFields
|
||||
}
|
||||
|
||||
// EnumError. ErrorDetails: allowed
|
||||
EnumError struct {
|
||||
ResultErrorFields
|
||||
@ -71,6 +86,11 @@ type (
|
||||
ResultErrorFields
|
||||
}
|
||||
|
||||
// ArrayContainsError. ErrorDetails:
|
||||
ArrayContainsError struct {
|
||||
ResultErrorFields
|
||||
}
|
||||
|
||||
// ArrayMinPropertiesError. ErrorDetails: min
|
||||
ArrayMinPropertiesError struct {
|
||||
ResultErrorFields
|
||||
@ -91,6 +111,11 @@ type (
|
||||
ResultErrorFields
|
||||
}
|
||||
|
||||
// InvalidPopertyNameError. ErrorDetails: property
|
||||
InvalidPropertyNameError struct {
|
||||
ResultErrorFields
|
||||
}
|
||||
|
||||
// StringLengthGTEError. ErrorDetails: min
|
||||
StringLengthGTEError struct {
|
||||
ResultErrorFields
|
||||
@ -135,10 +160,20 @@ type (
|
||||
NumberLTError struct {
|
||||
ResultErrorFields
|
||||
}
|
||||
|
||||
// ConditionThenError. ErrorDetails: -
|
||||
ConditionThenError struct {
|
||||
ResultErrorFields
|
||||
}
|
||||
|
||||
// ConditionElseError. ErrorDetails: -
|
||||
ConditionElseError struct {
|
||||
ResultErrorFields
|
||||
}
|
||||
)
|
||||
|
||||
// newError takes a ResultError type and sets the type, context, description, details, value, and field
|
||||
func newError(err ResultError, context *jsonContext, value interface{}, locale locale, details ErrorDetails) {
|
||||
func newError(err ResultError, context *JsonContext, value interface{}, locale locale, details ErrorDetails) {
|
||||
var t string
|
||||
var d string
|
||||
switch err.(type) {
|
||||
@ -166,6 +201,9 @@ func newError(err ResultError, context *jsonContext, value interface{}, locale l
|
||||
case *InternalError:
|
||||
t = "internal"
|
||||
d = locale.Internal()
|
||||
case *ConstError:
|
||||
t = "const"
|
||||
d = locale.Const()
|
||||
case *EnumError:
|
||||
t = "enum"
|
||||
d = locale.Enum()
|
||||
@ -181,6 +219,9 @@ func newError(err ResultError, context *jsonContext, value interface{}, locale l
|
||||
case *ItemsMustBeUniqueError:
|
||||
t = "unique"
|
||||
d = locale.Unique()
|
||||
case *ArrayContainsError:
|
||||
t = "contains"
|
||||
d = locale.ArrayContains()
|
||||
case *ArrayMinPropertiesError:
|
||||
t = "array_min_properties"
|
||||
d = locale.ArrayMinProperties()
|
||||
@ -193,6 +234,9 @@ func newError(err ResultError, context *jsonContext, value interface{}, locale l
|
||||
case *InvalidPropertyPatternError:
|
||||
t = "invalid_property_pattern"
|
||||
d = locale.InvalidPropertyPattern()
|
||||
case *InvalidPropertyNameError:
|
||||
t = "invalid_property_name"
|
||||
d = locale.InvalidPropertyName()
|
||||
case *StringLengthGTEError:
|
||||
t = "string_gte"
|
||||
d = locale.StringGTE()
|
||||
@ -220,23 +264,61 @@ func newError(err ResultError, context *jsonContext, value interface{}, locale l
|
||||
case *NumberLTError:
|
||||
t = "number_lt"
|
||||
d = locale.NumberLT()
|
||||
case *ConditionThenError:
|
||||
t = "condition_then"
|
||||
d = locale.ConditionThen()
|
||||
case *ConditionElseError:
|
||||
t = "condition_else"
|
||||
d = locale.ConditionElse()
|
||||
}
|
||||
|
||||
err.SetType(t)
|
||||
err.SetContext(context)
|
||||
err.SetValue(value)
|
||||
err.SetDetails(details)
|
||||
err.SetDescriptionFormat(d)
|
||||
details["field"] = err.Field()
|
||||
err.SetDescription(formatErrorDescription(d, details))
|
||||
}
|
||||
|
||||
// formatErrorDescription takes a string in this format: %field% is required
|
||||
// and converts it to a string with replacements. The fields come from
|
||||
// the ErrorDetails struct and vary for each type of error.
|
||||
func formatErrorDescription(s string, details ErrorDetails) string {
|
||||
for name, val := range details {
|
||||
s = strings.Replace(s, "%"+strings.ToLower(name)+"%", fmt.Sprintf("%v", val), -1)
|
||||
if _, exists := details["context"]; !exists && context != nil {
|
||||
details["context"] = context.String()
|
||||
}
|
||||
|
||||
return s
|
||||
err.SetDescription(formatErrorDescription(err.DescriptionFormat(), details))
|
||||
}
|
||||
|
||||
// formatErrorDescription takes a string in the default text/template
|
||||
// format and converts it to a string with replacements. The fields come
|
||||
// from the ErrorDetails struct and vary for each type of error.
|
||||
func formatErrorDescription(s string, details ErrorDetails) string {
|
||||
|
||||
var tpl *template.Template
|
||||
var descrAsBuffer bytes.Buffer
|
||||
var err error
|
||||
|
||||
errorTemplates.RLock()
|
||||
tpl = errorTemplates.Lookup(s)
|
||||
errorTemplates.RUnlock()
|
||||
|
||||
if tpl == nil {
|
||||
errorTemplates.Lock()
|
||||
tpl = errorTemplates.New(s)
|
||||
|
||||
if ErrorTemplateFuncs != nil {
|
||||
tpl.Funcs(ErrorTemplateFuncs)
|
||||
}
|
||||
|
||||
tpl, err = tpl.Parse(s)
|
||||
errorTemplates.Unlock()
|
||||
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
err = tpl.Execute(&descrAsBuffer, details)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
return descrAsBuffer.String()
|
||||
}
|
||||
|
136
vendor/github.com/xeipuuv/gojsonschema/format_checkers.go
generated
vendored
136
vendor/github.com/xeipuuv/gojsonschema/format_checkers.go
generated
vendored
@ -3,7 +3,6 @@ package gojsonschema
|
||||
import (
|
||||
"net"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
@ -12,7 +11,7 @@ import (
|
||||
type (
|
||||
// FormatChecker is the interface all formatters added to FormatCheckerChain must implement
|
||||
FormatChecker interface {
|
||||
IsFormat(input string) bool
|
||||
IsFormat(input interface{}) bool
|
||||
}
|
||||
|
||||
// FormatCheckerChain holds the formatters
|
||||
@ -52,14 +51,20 @@ type (
|
||||
// http://tools.ietf.org/html/rfc3339#section-5.6
|
||||
DateTimeFormatChecker struct{}
|
||||
|
||||
// URIFormatCheckers validates a URI with a valid Scheme per RFC3986
|
||||
// URIFormatChecker validates a URI with a valid Scheme per RFC3986
|
||||
URIFormatChecker struct{}
|
||||
|
||||
// URIReferenceFormatChecker validates a URI or relative-reference per RFC3986
|
||||
URIReferenceFormatChecker struct{}
|
||||
|
||||
// HostnameFormatChecker validates a hostname is in the correct format
|
||||
HostnameFormatChecker struct{}
|
||||
|
||||
// UUIDFormatChecker validates a UUID is in the correct format
|
||||
UUIDFormatChecker struct{}
|
||||
|
||||
// RegexFormatChecker validates a regex is in the correct format
|
||||
RegexFormatChecker struct{}
|
||||
)
|
||||
|
||||
var (
|
||||
@ -67,13 +72,15 @@ var (
|
||||
// so library users can add custom formatters
|
||||
FormatCheckers = FormatCheckerChain{
|
||||
formatters: map[string]FormatChecker{
|
||||
"date-time": DateTimeFormatChecker{},
|
||||
"hostname": HostnameFormatChecker{},
|
||||
"email": EmailFormatChecker{},
|
||||
"ipv4": IPV4FormatChecker{},
|
||||
"ipv6": IPV6FormatChecker{},
|
||||
"uri": URIFormatChecker{},
|
||||
"uuid": UUIDFormatChecker{},
|
||||
"date-time": DateTimeFormatChecker{},
|
||||
"hostname": HostnameFormatChecker{},
|
||||
"email": EmailFormatChecker{},
|
||||
"ipv4": IPV4FormatChecker{},
|
||||
"ipv6": IPV6FormatChecker{},
|
||||
"uri": URIFormatChecker{},
|
||||
"uri-reference": URIReferenceFormatChecker{},
|
||||
"uuid": UUIDFormatChecker{},
|
||||
"regex": RegexFormatChecker{},
|
||||
},
|
||||
}
|
||||
|
||||
@ -117,32 +124,50 @@ func (c *FormatCheckerChain) IsFormat(name string, input interface{}) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
if !isKind(input, reflect.String) {
|
||||
return f.IsFormat(input)
|
||||
}
|
||||
|
||||
func (f EmailFormatChecker) IsFormat(input interface{}) bool {
|
||||
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
inputString := input.(string)
|
||||
|
||||
return f.IsFormat(inputString)
|
||||
}
|
||||
|
||||
func (f EmailFormatChecker) IsFormat(input string) bool {
|
||||
return rxEmail.MatchString(input)
|
||||
return rxEmail.MatchString(asString)
|
||||
}
|
||||
|
||||
// Credit: https://github.com/asaskevich/govalidator
|
||||
func (f IPV4FormatChecker) IsFormat(input string) bool {
|
||||
ip := net.ParseIP(input)
|
||||
return ip != nil && strings.Contains(input, ".")
|
||||
func (f IPV4FormatChecker) IsFormat(input interface{}) bool {
|
||||
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
ip := net.ParseIP(asString)
|
||||
return ip != nil && strings.Contains(asString, ".")
|
||||
}
|
||||
|
||||
// Credit: https://github.com/asaskevich/govalidator
|
||||
func (f IPV6FormatChecker) IsFormat(input string) bool {
|
||||
ip := net.ParseIP(input)
|
||||
return ip != nil && strings.Contains(input, ":")
|
||||
func (f IPV6FormatChecker) IsFormat(input interface{}) bool {
|
||||
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
ip := net.ParseIP(asString)
|
||||
return ip != nil && strings.Contains(asString, ":")
|
||||
}
|
||||
|
||||
func (f DateTimeFormatChecker) IsFormat(input string) bool {
|
||||
func (f DateTimeFormatChecker) IsFormat(input interface{}) bool {
|
||||
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
formats := []string{
|
||||
"15:04:05",
|
||||
"15:04:05Z07:00",
|
||||
@ -152,7 +177,7 @@ func (f DateTimeFormatChecker) IsFormat(input string) bool {
|
||||
}
|
||||
|
||||
for _, format := range formats {
|
||||
if _, err := time.Parse(format, input); err == nil {
|
||||
if _, err := time.Parse(format, asString); err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -160,8 +185,14 @@ func (f DateTimeFormatChecker) IsFormat(input string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (f URIFormatChecker) IsFormat(input string) bool {
|
||||
u, err := url.Parse(input)
|
||||
func (f URIFormatChecker) IsFormat(input interface{}) bool {
|
||||
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
u, err := url.Parse(asString)
|
||||
if err != nil || u.Scheme == "" {
|
||||
return false
|
||||
}
|
||||
@ -169,10 +200,51 @@ func (f URIFormatChecker) IsFormat(input string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (f HostnameFormatChecker) IsFormat(input string) bool {
|
||||
return rxHostname.MatchString(input) && len(input) < 256
|
||||
func (f URIReferenceFormatChecker) IsFormat(input interface{}) bool {
|
||||
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
_, err := url.Parse(asString)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (f UUIDFormatChecker) IsFormat(input string) bool {
|
||||
return rxUUID.MatchString(input)
|
||||
func (f HostnameFormatChecker) IsFormat(input interface{}) bool {
|
||||
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
return rxHostname.MatchString(asString) && len(asString) < 256
|
||||
}
|
||||
|
||||
func (f UUIDFormatChecker) IsFormat(input interface{}) bool {
|
||||
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
return rxUUID.MatchString(asString)
|
||||
}
|
||||
|
||||
// IsFormat implements FormatChecker interface.
|
||||
func (f RegexFormatChecker) IsFormat(input interface{}) bool {
|
||||
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
if asString == "" {
|
||||
return true
|
||||
}
|
||||
_, err := regexp.Compile(asString)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
7
vendor/github.com/xeipuuv/gojsonschema/glide.yaml
generated
vendored
7
vendor/github.com/xeipuuv/gojsonschema/glide.yaml
generated
vendored
@ -7,6 +7,7 @@ import:
|
||||
|
||||
- package: github.com/xeipuuv/gojsonreference
|
||||
|
||||
- package: github.com/stretchr/testify/assert
|
||||
version: ^1.1.3
|
||||
|
||||
testImport:
|
||||
- package: github.com/stretchr/testify
|
||||
subpackages:
|
||||
- assert
|
||||
|
16
vendor/github.com/xeipuuv/gojsonschema/jsonContext.go
generated
vendored
16
vendor/github.com/xeipuuv/gojsonschema/jsonContext.go
generated
vendored
@ -26,20 +26,20 @@ package gojsonschema
|
||||
|
||||
import "bytes"
|
||||
|
||||
// jsonContext implements a persistent linked-list of strings
|
||||
type jsonContext struct {
|
||||
// JsonContext implements a persistent linked-list of strings
|
||||
type JsonContext struct {
|
||||
head string
|
||||
tail *jsonContext
|
||||
tail *JsonContext
|
||||
}
|
||||
|
||||
func newJsonContext(head string, tail *jsonContext) *jsonContext {
|
||||
return &jsonContext{head, tail}
|
||||
func NewJsonContext(head string, tail *JsonContext) *JsonContext {
|
||||
return &JsonContext{head, tail}
|
||||
}
|
||||
|
||||
// String displays the context in reverse.
|
||||
// This plays well with the data structure's persistent nature with
|
||||
// Cons and a json document's tree structure.
|
||||
func (c *jsonContext) String(del ...string) string {
|
||||
func (c *JsonContext) String(del ...string) string {
|
||||
byteArr := make([]byte, 0, c.stringLen())
|
||||
buf := bytes.NewBuffer(byteArr)
|
||||
c.writeStringToBuffer(buf, del)
|
||||
@ -47,7 +47,7 @@ func (c *jsonContext) String(del ...string) string {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (c *jsonContext) stringLen() int {
|
||||
func (c *JsonContext) stringLen() int {
|
||||
length := 0
|
||||
if c.tail != nil {
|
||||
length = c.tail.stringLen() + 1 // add 1 for "."
|
||||
@ -57,7 +57,7 @@ func (c *jsonContext) stringLen() int {
|
||||
return length
|
||||
}
|
||||
|
||||
func (c *jsonContext) writeStringToBuffer(buf *bytes.Buffer, del []string) {
|
||||
func (c *JsonContext) writeStringToBuffer(buf *bytes.Buffer, del []string) {
|
||||
if c.tail != nil {
|
||||
c.tail.writeStringToBuffer(buf, del)
|
||||
|
||||
|
244
vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go
generated
vendored
244
vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go
generated
vendored
@ -33,6 +33,7 @@ import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
@ -40,34 +41,92 @@ import (
|
||||
"github.com/xeipuuv/gojsonreference"
|
||||
)
|
||||
|
||||
var osFS = osFileSystem(os.Open)
|
||||
|
||||
// JSON loader interface
|
||||
|
||||
type JSONLoader interface {
|
||||
jsonSource() interface{}
|
||||
loadJSON() (interface{}, error)
|
||||
loadSchema() (*Schema, error)
|
||||
JsonSource() interface{}
|
||||
LoadJSON() (interface{}, error)
|
||||
JsonReference() (gojsonreference.JsonReference, error)
|
||||
LoaderFactory() JSONLoaderFactory
|
||||
}
|
||||
|
||||
type JSONLoaderFactory interface {
|
||||
New(source string) JSONLoader
|
||||
}
|
||||
|
||||
type DefaultJSONLoaderFactory struct {
|
||||
}
|
||||
|
||||
type FileSystemJSONLoaderFactory struct {
|
||||
fs http.FileSystem
|
||||
}
|
||||
|
||||
func (d DefaultJSONLoaderFactory) New(source string) JSONLoader {
|
||||
return &jsonReferenceLoader{
|
||||
fs: osFS,
|
||||
source: source,
|
||||
}
|
||||
}
|
||||
|
||||
func (f FileSystemJSONLoaderFactory) New(source string) JSONLoader {
|
||||
return &jsonReferenceLoader{
|
||||
fs: f.fs,
|
||||
source: source,
|
||||
}
|
||||
}
|
||||
|
||||
// osFileSystem is a functional wrapper for os.Open that implements http.FileSystem.
|
||||
type osFileSystem func(string) (*os.File, error)
|
||||
|
||||
func (o osFileSystem) Open(name string) (http.File, error) {
|
||||
return o(name)
|
||||
}
|
||||
|
||||
// JSON Reference loader
|
||||
// references are used to load JSONs from files and HTTP
|
||||
|
||||
type jsonReferenceLoader struct {
|
||||
fs http.FileSystem
|
||||
source string
|
||||
}
|
||||
|
||||
func (l *jsonReferenceLoader) jsonSource() interface{} {
|
||||
func (l *jsonReferenceLoader) JsonSource() interface{} {
|
||||
return l.source
|
||||
}
|
||||
|
||||
func NewReferenceLoader(source string) *jsonReferenceLoader {
|
||||
return &jsonReferenceLoader{source: source}
|
||||
func (l *jsonReferenceLoader) JsonReference() (gojsonreference.JsonReference, error) {
|
||||
return gojsonreference.NewJsonReference(l.JsonSource().(string))
|
||||
}
|
||||
|
||||
func (l *jsonReferenceLoader) loadJSON() (interface{}, error) {
|
||||
func (l *jsonReferenceLoader) LoaderFactory() JSONLoaderFactory {
|
||||
return &FileSystemJSONLoaderFactory{
|
||||
fs: l.fs,
|
||||
}
|
||||
}
|
||||
|
||||
// NewReferenceLoader returns a JSON reference loader using the given source and the local OS file system.
|
||||
func NewReferenceLoader(source string) *jsonReferenceLoader {
|
||||
return &jsonReferenceLoader{
|
||||
fs: osFS,
|
||||
source: source,
|
||||
}
|
||||
}
|
||||
|
||||
// NewReferenceLoaderFileSystem returns a JSON reference loader using the given source and file system.
|
||||
func NewReferenceLoaderFileSystem(source string, fs http.FileSystem) *jsonReferenceLoader {
|
||||
return &jsonReferenceLoader{
|
||||
fs: fs,
|
||||
source: source,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) {
|
||||
|
||||
var err error
|
||||
|
||||
reference, err := gojsonreference.NewJsonReference(l.jsonSource().(string))
|
||||
reference, err := gojsonreference.NewJsonReference(l.JsonSource().(string))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -79,7 +138,7 @@ func (l *jsonReferenceLoader) loadJSON() (interface{}, error) {
|
||||
|
||||
if reference.HasFileScheme {
|
||||
|
||||
filename := strings.Replace(refToUrl.String(), "file://", "", -1)
|
||||
filename := strings.Replace(refToUrl.GetUrl().Path, "file://", "", -1)
|
||||
if runtime.GOOS == "windows" {
|
||||
// on Windows, a file URL may have an extra leading slash, use slashes
|
||||
// instead of backslashes, and have spaces escaped
|
||||
@ -87,7 +146,6 @@ func (l *jsonReferenceLoader) loadJSON() (interface{}, error) {
|
||||
filename = filename[1:]
|
||||
}
|
||||
filename = filepath.FromSlash(filename)
|
||||
filename = strings.Replace(filename, "%20", " ", -1)
|
||||
}
|
||||
|
||||
document, err = l.loadFromFile(filename)
|
||||
@ -108,33 +166,6 @@ func (l *jsonReferenceLoader) loadJSON() (interface{}, error) {
|
||||
|
||||
}
|
||||
|
||||
func (l *jsonReferenceLoader) loadSchema() (*Schema, error) {
|
||||
|
||||
var err error
|
||||
|
||||
d := Schema{}
|
||||
d.pool = newSchemaPool()
|
||||
d.referencePool = newSchemaReferencePool()
|
||||
|
||||
d.documentReference, err = gojsonreference.NewJsonReference(l.jsonSource().(string))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
spd, err := d.pool.GetDocument(d.documentReference)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = d.parse(spd.Document)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &d, nil
|
||||
|
||||
}
|
||||
|
||||
func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error) {
|
||||
|
||||
resp, err := http.Get(address)
|
||||
@ -144,7 +175,7 @@ func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error)
|
||||
|
||||
// must return HTTP Status 200 OK
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.New(formatErrorDescription(Locale.httpBadStatus(), ErrorDetails{"status": resp.Status}))
|
||||
return nil, errors.New(formatErrorDescription(Locale.HttpBadStatus(), ErrorDetails{"status": resp.Status}))
|
||||
}
|
||||
|
||||
bodyBuff, err := ioutil.ReadAll(resp.Body)
|
||||
@ -157,8 +188,13 @@ func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error)
|
||||
}
|
||||
|
||||
func (l *jsonReferenceLoader) loadFromFile(path string) (interface{}, error) {
|
||||
f, err := l.fs.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
bodyBuff, err := ioutil.ReadFile(path)
|
||||
bodyBuff, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -173,45 +209,52 @@ type jsonStringLoader struct {
|
||||
source string
|
||||
}
|
||||
|
||||
func (l *jsonStringLoader) jsonSource() interface{} {
|
||||
func (l *jsonStringLoader) JsonSource() interface{} {
|
||||
return l.source
|
||||
}
|
||||
|
||||
func (l *jsonStringLoader) JsonReference() (gojsonreference.JsonReference, error) {
|
||||
return gojsonreference.NewJsonReference("#")
|
||||
}
|
||||
|
||||
func (l *jsonStringLoader) LoaderFactory() JSONLoaderFactory {
|
||||
return &DefaultJSONLoaderFactory{}
|
||||
}
|
||||
|
||||
func NewStringLoader(source string) *jsonStringLoader {
|
||||
return &jsonStringLoader{source: source}
|
||||
}
|
||||
|
||||
func (l *jsonStringLoader) loadJSON() (interface{}, error) {
|
||||
func (l *jsonStringLoader) LoadJSON() (interface{}, error) {
|
||||
|
||||
return decodeJsonUsingNumber(strings.NewReader(l.jsonSource().(string)))
|
||||
return decodeJsonUsingNumber(strings.NewReader(l.JsonSource().(string)))
|
||||
|
||||
}
|
||||
|
||||
func (l *jsonStringLoader) loadSchema() (*Schema, error) {
|
||||
// JSON bytes loader
|
||||
|
||||
var err error
|
||||
type jsonBytesLoader struct {
|
||||
source []byte
|
||||
}
|
||||
|
||||
document, err := l.loadJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (l *jsonBytesLoader) JsonSource() interface{} {
|
||||
return l.source
|
||||
}
|
||||
|
||||
d := Schema{}
|
||||
d.pool = newSchemaPool()
|
||||
d.referencePool = newSchemaReferencePool()
|
||||
d.documentReference, err = gojsonreference.NewJsonReference("#")
|
||||
d.pool.SetStandaloneDocument(document)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (l *jsonBytesLoader) JsonReference() (gojsonreference.JsonReference, error) {
|
||||
return gojsonreference.NewJsonReference("#")
|
||||
}
|
||||
|
||||
err = d.parse(document)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (l *jsonBytesLoader) LoaderFactory() JSONLoaderFactory {
|
||||
return &DefaultJSONLoaderFactory{}
|
||||
}
|
||||
|
||||
return &d, nil
|
||||
func NewBytesLoader(source []byte) *jsonBytesLoader {
|
||||
return &jsonBytesLoader{source: source}
|
||||
}
|
||||
|
||||
func (l *jsonBytesLoader) LoadJSON() (interface{}, error) {
|
||||
return decodeJsonUsingNumber(bytes.NewReader(l.JsonSource().([]byte)))
|
||||
}
|
||||
|
||||
// JSON Go (types) loader
|
||||
@ -221,19 +264,27 @@ type jsonGoLoader struct {
|
||||
source interface{}
|
||||
}
|
||||
|
||||
func (l *jsonGoLoader) jsonSource() interface{} {
|
||||
func (l *jsonGoLoader) JsonSource() interface{} {
|
||||
return l.source
|
||||
}
|
||||
|
||||
func (l *jsonGoLoader) JsonReference() (gojsonreference.JsonReference, error) {
|
||||
return gojsonreference.NewJsonReference("#")
|
||||
}
|
||||
|
||||
func (l *jsonGoLoader) LoaderFactory() JSONLoaderFactory {
|
||||
return &DefaultJSONLoaderFactory{}
|
||||
}
|
||||
|
||||
func NewGoLoader(source interface{}) *jsonGoLoader {
|
||||
return &jsonGoLoader{source: source}
|
||||
}
|
||||
|
||||
func (l *jsonGoLoader) loadJSON() (interface{}, error) {
|
||||
func (l *jsonGoLoader) LoadJSON() (interface{}, error) {
|
||||
|
||||
// convert it to a compliant JSON first to avoid types "mismatches"
|
||||
|
||||
jsonBytes, err := json.Marshal(l.jsonSource())
|
||||
jsonBytes, err := json.Marshal(l.JsonSource())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -242,31 +293,58 @@ func (l *jsonGoLoader) loadJSON() (interface{}, error) {
|
||||
|
||||
}
|
||||
|
||||
func (l *jsonGoLoader) loadSchema() (*Schema, error) {
|
||||
type jsonIOLoader struct {
|
||||
buf *bytes.Buffer
|
||||
}
|
||||
|
||||
var err error
|
||||
func NewReaderLoader(source io.Reader) (*jsonIOLoader, io.Reader) {
|
||||
buf := &bytes.Buffer{}
|
||||
return &jsonIOLoader{buf: buf}, io.TeeReader(source, buf)
|
||||
}
|
||||
|
||||
document, err := l.loadJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func NewWriterLoader(source io.Writer) (*jsonIOLoader, io.Writer) {
|
||||
buf := &bytes.Buffer{}
|
||||
return &jsonIOLoader{buf: buf}, io.MultiWriter(source, buf)
|
||||
}
|
||||
|
||||
d := Schema{}
|
||||
d.pool = newSchemaPool()
|
||||
d.referencePool = newSchemaReferencePool()
|
||||
d.documentReference, err = gojsonreference.NewJsonReference("#")
|
||||
d.pool.SetStandaloneDocument(document)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (l *jsonIOLoader) JsonSource() interface{} {
|
||||
return l.buf.String()
|
||||
}
|
||||
|
||||
err = d.parse(document)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func (l *jsonIOLoader) LoadJSON() (interface{}, error) {
|
||||
return decodeJsonUsingNumber(l.buf)
|
||||
}
|
||||
|
||||
return &d, nil
|
||||
func (l *jsonIOLoader) JsonReference() (gojsonreference.JsonReference, error) {
|
||||
return gojsonreference.NewJsonReference("#")
|
||||
}
|
||||
|
||||
func (l *jsonIOLoader) LoaderFactory() JSONLoaderFactory {
|
||||
return &DefaultJSONLoaderFactory{}
|
||||
}
|
||||
|
||||
// JSON raw loader
|
||||
// In case the JSON is already marshalled to interface{} use this loader
|
||||
// This is used for testing as otherwise there is no guarantee the JSON is marshalled
|
||||
// "properly" by using https://golang.org/pkg/encoding/json/#Decoder.UseNumber
|
||||
type jsonRawLoader struct {
|
||||
source interface{}
|
||||
}
|
||||
|
||||
func NewRawLoader(source interface{}) *jsonRawLoader {
|
||||
return &jsonRawLoader{source: source}
|
||||
}
|
||||
func (l *jsonRawLoader) JsonSource() interface{} {
|
||||
return l.source
|
||||
}
|
||||
func (l *jsonRawLoader) LoadJSON() (interface{}, error) {
|
||||
return l.source, nil
|
||||
}
|
||||
func (l *jsonRawLoader) JsonReference() (gojsonreference.JsonReference, error) {
|
||||
return gojsonreference.NewJsonReference("#")
|
||||
}
|
||||
func (l *jsonRawLoader) LoaderFactory() JSONLoaderFactory {
|
||||
return &DefaultJSONLoaderFactory{}
|
||||
}
|
||||
|
||||
func decodeJsonUsingNumber(r io.Reader) (interface{}, error) {
|
||||
|
124
vendor/github.com/xeipuuv/gojsonschema/locales.go
generated
vendored
124
vendor/github.com/xeipuuv/gojsonschema/locales.go
generated
vendored
@ -26,7 +26,7 @@
|
||||
package gojsonschema
|
||||
|
||||
type (
|
||||
// locale is an interface for definining custom error strings
|
||||
// locale is an interface for defining custom error strings
|
||||
locale interface {
|
||||
Required() string
|
||||
InvalidType() string
|
||||
@ -36,15 +36,19 @@ type (
|
||||
NumberNot() string
|
||||
MissingDependency() string
|
||||
Internal() string
|
||||
Const() string
|
||||
Enum() string
|
||||
ArrayNotEnoughItems() string
|
||||
ArrayNoAdditionalItems() string
|
||||
ArrayMinItems() string
|
||||
ArrayMaxItems() string
|
||||
Unique() string
|
||||
ArrayContains() string
|
||||
ArrayMinProperties() string
|
||||
ArrayMaxProperties() string
|
||||
AdditionalPropertyNotAllowed() string
|
||||
InvalidPropertyPattern() string
|
||||
InvalidPropertyName() string
|
||||
StringGTE() string
|
||||
StringLTE() string
|
||||
DoesNotMatchPattern() string
|
||||
@ -72,7 +76,11 @@ type (
|
||||
ReferenceMustBeCanonical() string
|
||||
NotAValidType() string
|
||||
Duplicated() string
|
||||
httpBadStatus() string
|
||||
HttpBadStatus() string
|
||||
ParseError() string
|
||||
|
||||
ConditionThen() string
|
||||
ConditionElse() string
|
||||
|
||||
// ErrorFormat
|
||||
ErrorFormat() string
|
||||
@ -83,11 +91,11 @@ type (
|
||||
)
|
||||
|
||||
func (l DefaultLocale) Required() string {
|
||||
return `%property% is required`
|
||||
return `{{.property}} is required`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) InvalidType() string {
|
||||
return `Invalid type. Expected: %expected%, given: %given%`
|
||||
return `Invalid type. Expected: {{.expected}}, given: {{.given}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) NumberAnyOf() string {
|
||||
@ -107,164 +115,194 @@ func (l DefaultLocale) NumberNot() string {
|
||||
}
|
||||
|
||||
func (l DefaultLocale) MissingDependency() string {
|
||||
return `Has a dependency on %dependency%`
|
||||
return `Has a dependency on {{.dependency}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) Internal() string {
|
||||
return `Internal Error %error%`
|
||||
return `Internal Error {{.error}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) Const() string {
|
||||
return `{{.field}} does not match: {{.allowed}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) Enum() string {
|
||||
return `%field% must be one of the following: %allowed%`
|
||||
return `{{.field}} must be one of the following: {{.allowed}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) ArrayNoAdditionalItems() string {
|
||||
return `No additional items allowed on array`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) ArrayNotEnoughItems() string {
|
||||
return `Not enough items on array to match positional list of schema`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) ArrayMinItems() string {
|
||||
return `Array must have at least %min% items`
|
||||
return `Array must have at least {{.min}} items`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) ArrayMaxItems() string {
|
||||
return `Array must have at most %max% items`
|
||||
return `Array must have at most {{.max}} items`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) Unique() string {
|
||||
return `%type% items must be unique`
|
||||
return `{{.type}} items must be unique`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) ArrayContains() string {
|
||||
return `At least one of the items must match`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) ArrayMinProperties() string {
|
||||
return `Must have at least %min% properties`
|
||||
return `Must have at least {{.min}} properties`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) ArrayMaxProperties() string {
|
||||
return `Must have at most %max% properties`
|
||||
return `Must have at most {{.max}} properties`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) AdditionalPropertyNotAllowed() string {
|
||||
return `Additional property %property% is not allowed`
|
||||
return `Additional property {{.property}} is not allowed`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) InvalidPropertyPattern() string {
|
||||
return `Property "%property%" does not match pattern %pattern%`
|
||||
return `Property "{{.property}}" does not match pattern {{.pattern}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) InvalidPropertyName() string {
|
||||
return `Property name of "{{.property}}" does not match`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) StringGTE() string {
|
||||
return `String length must be greater than or equal to %min%`
|
||||
return `String length must be greater than or equal to {{.min}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) StringLTE() string {
|
||||
return `String length must be less than or equal to %max%`
|
||||
return `String length must be less than or equal to {{.max}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) DoesNotMatchPattern() string {
|
||||
return `Does not match pattern '%pattern%'`
|
||||
return `Does not match pattern '{{.pattern}}'`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) DoesNotMatchFormat() string {
|
||||
return `Does not match format '%format%'`
|
||||
return `Does not match format '{{.format}}'`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) MultipleOf() string {
|
||||
return `Must be a multiple of %multiple%`
|
||||
return `Must be a multiple of {{.multiple}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) NumberGTE() string {
|
||||
return `Must be greater than or equal to %min%`
|
||||
return `Must be greater than or equal to {{.min}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) NumberGT() string {
|
||||
return `Must be greater than %min%`
|
||||
return `Must be greater than {{.min}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) NumberLTE() string {
|
||||
return `Must be less than or equal to %max%`
|
||||
return `Must be less than or equal to {{.max}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) NumberLT() string {
|
||||
return `Must be less than %max%`
|
||||
return `Must be less than {{.max}}`
|
||||
}
|
||||
|
||||
// Schema validators
|
||||
func (l DefaultLocale) RegexPattern() string {
|
||||
return `Invalid regex pattern '%pattern%'`
|
||||
return `Invalid regex pattern '{{.pattern}}'`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) GreaterThanZero() string {
|
||||
return `%number% must be strictly greater than 0`
|
||||
return `{{.number}} must be strictly greater than 0`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) MustBeOfA() string {
|
||||
return `%x% must be of a %y%`
|
||||
return `{{.x}} must be of a {{.y}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) MustBeOfAn() string {
|
||||
return `%x% must be of an %y%`
|
||||
return `{{.x}} must be of an {{.y}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) CannotBeUsedWithout() string {
|
||||
return `%x% cannot be used without %y%`
|
||||
return `{{.x}} cannot be used without {{.y}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) CannotBeGT() string {
|
||||
return `%x% cannot be greater than %y%`
|
||||
return `{{.x}} cannot be greater than {{.y}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) MustBeOfType() string {
|
||||
return `%key% must be of type %type%`
|
||||
return `{{.key}} must be of type {{.type}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) MustBeValidRegex() string {
|
||||
return `%key% must be a valid regex`
|
||||
return `{{.key}} must be a valid regex`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) MustBeValidFormat() string {
|
||||
return `%key% must be a valid format %given%`
|
||||
return `{{.key}} must be a valid format {{.given}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) MustBeGTEZero() string {
|
||||
return `%key% must be greater than or equal to 0`
|
||||
return `{{.key}} must be greater than or equal to 0`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) KeyCannotBeGreaterThan() string {
|
||||
return `%key% cannot be greater than %y%`
|
||||
return `{{.key}} cannot be greater than {{.y}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) KeyItemsMustBeOfType() string {
|
||||
return `%key% items must be %type%`
|
||||
return `{{.key}} items must be {{.type}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) KeyItemsMustBeUnique() string {
|
||||
return `%key% items must be unique`
|
||||
return `{{.key}} items must be unique`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) ReferenceMustBeCanonical() string {
|
||||
return `Reference %reference% must be canonical`
|
||||
return `Reference {{.reference}} must be canonical`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) NotAValidType() string {
|
||||
return `%type% is not a valid type -- `
|
||||
return `has a primitive type that is NOT VALID -- given: {{.given}} Expected valid values are:{{.expected}}`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) Duplicated() string {
|
||||
return `%type% type is duplicated`
|
||||
return `{{.type}} type is duplicated`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) httpBadStatus() string {
|
||||
return `Could not read schema from HTTP, response status is %status%`
|
||||
func (l DefaultLocale) HttpBadStatus() string {
|
||||
return `Could not read schema from HTTP, response status is {{.status}}`
|
||||
}
|
||||
|
||||
// Replacement options: field, description, context, value
|
||||
func (l DefaultLocale) ErrorFormat() string {
|
||||
return `%field%: %description%`
|
||||
return `{{.field}}: {{.description}}`
|
||||
}
|
||||
|
||||
//Parse error
|
||||
func (l DefaultLocale) ParseError() string {
|
||||
return `Expected: {{.expected}}, given: Invalid JSON`
|
||||
}
|
||||
|
||||
//If/Else
|
||||
func (l DefaultLocale) ConditionThen() string {
|
||||
return `Must validate "then" as "if" was valid`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) ConditionElse() string {
|
||||
return `Must validate "else" as "if" was not valid`
|
||||
}
|
||||
|
||||
const (
|
||||
STRING_NUMBER = "number"
|
||||
STRING_ARRAY_OF_STRINGS = "array of strings"
|
||||
STRING_ARRAY_OF_SCHEMAS = "array of schemas"
|
||||
STRING_SCHEMA = "schema"
|
||||
STRING_SCHEMA = "valid schema"
|
||||
STRING_SCHEMA_OR_ARRAY_OF_STRINGS = "schema or array of strings"
|
||||
STRING_PROPERTIES = "properties"
|
||||
STRING_DEPENDENCY = "dependency"
|
||||
|
44
vendor/github.com/xeipuuv/gojsonschema/result.go
generated
vendored
44
vendor/github.com/xeipuuv/gojsonschema/result.go
generated
vendored
@ -40,25 +40,29 @@ type (
|
||||
Field() string
|
||||
SetType(string)
|
||||
Type() string
|
||||
SetContext(*jsonContext)
|
||||
Context() *jsonContext
|
||||
SetContext(*JsonContext)
|
||||
Context() *JsonContext
|
||||
SetDescription(string)
|
||||
Description() string
|
||||
SetDescriptionFormat(string)
|
||||
DescriptionFormat() string
|
||||
SetValue(interface{})
|
||||
Value() interface{}
|
||||
SetDetails(ErrorDetails)
|
||||
Details() ErrorDetails
|
||||
String() string
|
||||
}
|
||||
|
||||
// ResultErrorFields holds the fields for each ResultError implementation.
|
||||
// ResultErrorFields implements the ResultError interface, so custom errors
|
||||
// can be defined by just embedding this type
|
||||
ResultErrorFields struct {
|
||||
errorType string // A string with the type of error (i.e. invalid_type)
|
||||
context *jsonContext // Tree like notation of the part that failed the validation. ex (root).a.b ...
|
||||
description string // A human readable error message
|
||||
value interface{} // Value given by the JSON file that is the source of the error
|
||||
details ErrorDetails
|
||||
errorType string // A string with the type of error (i.e. invalid_type)
|
||||
context *JsonContext // Tree like notation of the part that failed the validation. ex (root).a.b ...
|
||||
description string // A human readable error message
|
||||
descriptionFormat string // A format for human readable error message
|
||||
value interface{} // Value given by the JSON file that is the source of the error
|
||||
details ErrorDetails
|
||||
}
|
||||
|
||||
Result struct {
|
||||
@ -89,11 +93,11 @@ func (v *ResultErrorFields) Type() string {
|
||||
return v.errorType
|
||||
}
|
||||
|
||||
func (v *ResultErrorFields) SetContext(context *jsonContext) {
|
||||
func (v *ResultErrorFields) SetContext(context *JsonContext) {
|
||||
v.context = context
|
||||
}
|
||||
|
||||
func (v *ResultErrorFields) Context() *jsonContext {
|
||||
func (v *ResultErrorFields) Context() *JsonContext {
|
||||
return v.context
|
||||
}
|
||||
|
||||
@ -105,6 +109,14 @@ func (v *ResultErrorFields) Description() string {
|
||||
return v.description
|
||||
}
|
||||
|
||||
func (v *ResultErrorFields) SetDescriptionFormat(descriptionFormat string) {
|
||||
v.descriptionFormat = descriptionFormat
|
||||
}
|
||||
|
||||
func (v *ResultErrorFields) DescriptionFormat() string {
|
||||
return v.descriptionFormat
|
||||
}
|
||||
|
||||
func (v *ResultErrorFields) SetValue(value interface{}) {
|
||||
v.value = value
|
||||
}
|
||||
@ -154,7 +166,19 @@ func (v *Result) Errors() []ResultError {
|
||||
return v.errors
|
||||
}
|
||||
|
||||
func (v *Result) addError(err ResultError, context *jsonContext, value interface{}, details ErrorDetails) {
|
||||
// Add a fully filled error to the error set
|
||||
// SetDescription() will be called with the result of the parsed err.DescriptionFormat()
|
||||
func (v *Result) AddError(err ResultError, details ErrorDetails) {
|
||||
if _, exists := details["context"]; !exists && err.Context() != nil {
|
||||
details["context"] = err.Context().String()
|
||||
}
|
||||
|
||||
err.SetDescription(formatErrorDescription(err.DescriptionFormat(), details))
|
||||
|
||||
v.errors = append(v.errors, err)
|
||||
}
|
||||
|
||||
func (v *Result) addInternalError(err ResultError, context *JsonContext, value interface{}, details ErrorDetails) {
|
||||
newError(err, context, value, Locale, details)
|
||||
v.errors = append(v.errors, err)
|
||||
v.score -= 2 // results in a net -1 when added to the +1 we get at the end of the validation function
|
||||
|
372
vendor/github.com/xeipuuv/gojsonschema/schema.go
generated
vendored
372
vendor/github.com/xeipuuv/gojsonschema/schema.go
generated
vendored
@ -27,10 +27,11 @@
|
||||
package gojsonschema
|
||||
|
||||
import (
|
||||
// "encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"text/template"
|
||||
|
||||
"github.com/xeipuuv/gojsonreference"
|
||||
)
|
||||
@ -39,10 +40,47 @@ var (
|
||||
// Locale is the default locale to use
|
||||
// Library users can overwrite with their own implementation
|
||||
Locale locale = DefaultLocale{}
|
||||
|
||||
// ErrorTemplateFuncs allows you to define custom template funcs for use in localization.
|
||||
ErrorTemplateFuncs template.FuncMap
|
||||
)
|
||||
|
||||
func NewSchema(l JSONLoader) (*Schema, error) {
|
||||
return l.loadSchema()
|
||||
ref, err := l.JsonReference()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := Schema{}
|
||||
d.pool = newSchemaPool(l.LoaderFactory())
|
||||
d.documentReference = ref
|
||||
d.referencePool = newSchemaReferencePool()
|
||||
|
||||
var spd *schemaPoolDocument
|
||||
var doc interface{}
|
||||
if ref.String() != "" {
|
||||
// Get document from schema pool
|
||||
spd, err = d.pool.GetDocument(d.documentReference)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
doc = spd.Document
|
||||
} else {
|
||||
// Load JSON directly
|
||||
doc, err = l.LoadJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
d.pool.ParseReferences(doc, ref)
|
||||
|
||||
err = d.parse(doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &d, nil
|
||||
}
|
||||
|
||||
type Schema struct {
|
||||
@ -69,80 +107,91 @@ func (d *Schema) SetRootSchemaName(name string) {
|
||||
//
|
||||
func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) error {
|
||||
|
||||
// As of draft 6 "true" is equivalent to an empty schema "{}" and false equals "{"not":{}}"
|
||||
if isKind(documentNode, reflect.Bool) {
|
||||
b := documentNode.(bool)
|
||||
if b {
|
||||
documentNode = map[string]interface{}{}
|
||||
} else {
|
||||
documentNode = map[string]interface{}{"not": true}
|
||||
}
|
||||
}
|
||||
|
||||
if !isKind(documentNode, reflect.Map) {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
Locale.ParseError(),
|
||||
ErrorDetails{
|
||||
"expected": TYPE_OBJECT,
|
||||
"given": STRING_SCHEMA,
|
||||
"expected": STRING_SCHEMA,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
m := documentNode.(map[string]interface{})
|
||||
|
||||
if currentSchema == d.rootSchema {
|
||||
if currentSchema.parent == nil {
|
||||
currentSchema.ref = &d.documentReference
|
||||
}
|
||||
currentSchema.id = &d.documentReference
|
||||
|
||||
// $subSchema
|
||||
if existsMapKey(m, KEY_SCHEMA) {
|
||||
if !isKind(m[KEY_SCHEMA], reflect.String) {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{
|
||||
"expected": TYPE_STRING,
|
||||
"given": KEY_SCHEMA,
|
||||
},
|
||||
))
|
||||
}
|
||||
schemaRef := m[KEY_SCHEMA].(string)
|
||||
schemaReference, err := gojsonreference.NewJsonReference(schemaRef)
|
||||
currentSchema.subSchema = &schemaReference
|
||||
if err != nil {
|
||||
return err
|
||||
if existsMapKey(m, KEY_SCHEMA) && false {
|
||||
if !isKind(m[KEY_SCHEMA], reflect.String) {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{
|
||||
"expected": TYPE_STRING,
|
||||
"given": KEY_SCHEMA,
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// $ref
|
||||
if existsMapKey(m, KEY_REF) && !isKind(m[KEY_REF], reflect.String) {
|
||||
if currentSchema.id == nil && currentSchema.parent != nil {
|
||||
currentSchema.id = currentSchema.parent.id
|
||||
}
|
||||
|
||||
// In draft 6 the id keyword was renamed to $id
|
||||
// Use the old id by default
|
||||
keyID := KEY_ID_NEW
|
||||
if existsMapKey(m, KEY_ID) {
|
||||
keyID = KEY_ID
|
||||
}
|
||||
if existsMapKey(m, keyID) && !isKind(m[keyID], reflect.String) {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{
|
||||
"expected": TYPE_STRING,
|
||||
"given": KEY_REF,
|
||||
"given": keyID,
|
||||
},
|
||||
))
|
||||
}
|
||||
if k, ok := m[KEY_REF].(string); ok {
|
||||
|
||||
if sch, ok := d.referencePool.Get(currentSchema.ref.String() + k); ok {
|
||||
|
||||
currentSchema.refSchema = sch
|
||||
|
||||
if k, ok := m[keyID].(string); ok {
|
||||
jsonReference, err := gojsonreference.NewJsonReference(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if currentSchema == d.rootSchema {
|
||||
currentSchema.id = &jsonReference
|
||||
} else {
|
||||
|
||||
var err error
|
||||
err = d.parseReference(documentNode, currentSchema, k)
|
||||
ref, err := currentSchema.parent.id.Inherits(jsonReference)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
currentSchema.id = ref
|
||||
}
|
||||
}
|
||||
|
||||
// definitions
|
||||
if existsMapKey(m, KEY_DEFINITIONS) {
|
||||
if isKind(m[KEY_DEFINITIONS], reflect.Map) {
|
||||
currentSchema.definitions = make(map[string]*subSchema)
|
||||
for dk, dv := range m[KEY_DEFINITIONS].(map[string]interface{}) {
|
||||
if isKind(dv, reflect.Map) {
|
||||
newSchema := &subSchema{property: KEY_DEFINITIONS, parent: currentSchema, ref: currentSchema.ref}
|
||||
currentSchema.definitions[dk] = newSchema
|
||||
if isKind(m[KEY_DEFINITIONS], reflect.Map, reflect.Bool) {
|
||||
for _, dv := range m[KEY_DEFINITIONS].(map[string]interface{}) {
|
||||
if isKind(dv, reflect.Map, reflect.Bool) {
|
||||
|
||||
newSchema := &subSchema{property: KEY_DEFINITIONS, parent: currentSchema}
|
||||
|
||||
err := d.parseSchema(dv, newSchema)
|
||||
|
||||
if err != nil {
|
||||
return errors.New(err.Error())
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
@ -166,20 +215,6 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
||||
|
||||
}
|
||||
|
||||
// id
|
||||
if existsMapKey(m, KEY_ID) && !isKind(m[KEY_ID], reflect.String) {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{
|
||||
"expected": TYPE_STRING,
|
||||
"given": KEY_ID,
|
||||
},
|
||||
))
|
||||
}
|
||||
if k, ok := m[KEY_ID].(string); ok {
|
||||
currentSchema.id = &k
|
||||
}
|
||||
|
||||
// title
|
||||
if existsMapKey(m, KEY_TITLE) && !isKind(m[KEY_TITLE], reflect.String) {
|
||||
return errors.New(formatErrorDescription(
|
||||
@ -208,6 +243,39 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
||||
currentSchema.description = &k
|
||||
}
|
||||
|
||||
// $ref
|
||||
if existsMapKey(m, KEY_REF) && !isKind(m[KEY_REF], reflect.String) {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{
|
||||
"expected": TYPE_STRING,
|
||||
"given": KEY_REF,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
if k, ok := m[KEY_REF].(string); ok {
|
||||
|
||||
jsonReference, err := gojsonreference.NewJsonReference(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
currentSchema.ref = &jsonReference
|
||||
|
||||
if sch, ok := d.referencePool.Get(currentSchema.ref.String()); ok {
|
||||
currentSchema.refSchema = sch
|
||||
} else {
|
||||
err := d.parseReference(documentNode, currentSchema)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// type
|
||||
if existsMapKey(m, KEY_TYPE) {
|
||||
if isKind(m[KEY_TYPE], reflect.String) {
|
||||
@ -309,6 +377,26 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
||||
}
|
||||
}
|
||||
|
||||
// propertyNames
|
||||
if existsMapKey(m, KEY_PROPERTY_NAMES) {
|
||||
if isKind(m[KEY_PROPERTY_NAMES], reflect.Map, reflect.Bool) {
|
||||
newSchema := &subSchema{property: KEY_PROPERTY_NAMES, parent: currentSchema, ref: currentSchema.ref}
|
||||
currentSchema.propertyNames = newSchema
|
||||
err := d.parseSchema(m[KEY_PROPERTY_NAMES], newSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{
|
||||
"expected": STRING_SCHEMA,
|
||||
"given": KEY_PATTERN_PROPERTIES,
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// dependencies
|
||||
if existsMapKey(m, KEY_DEPENDENCIES) {
|
||||
err := d.parseDependencies(m[KEY_DEPENDENCIES], currentSchema)
|
||||
@ -321,7 +409,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
||||
if existsMapKey(m, KEY_ITEMS) {
|
||||
if isKind(m[KEY_ITEMS], reflect.Slice) {
|
||||
for _, itemElement := range m[KEY_ITEMS].([]interface{}) {
|
||||
if isKind(itemElement, reflect.Map) {
|
||||
if isKind(itemElement, reflect.Map, reflect.Bool) {
|
||||
newSchema := &subSchema{parent: currentSchema, property: KEY_ITEMS}
|
||||
newSchema.ref = currentSchema.ref
|
||||
currentSchema.AddItemsChild(newSchema)
|
||||
@ -340,7 +428,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
||||
}
|
||||
currentSchema.itemsChildrenIsSingleSchema = false
|
||||
}
|
||||
} else if isKind(m[KEY_ITEMS], reflect.Map) {
|
||||
} else if isKind(m[KEY_ITEMS], reflect.Map, reflect.Bool) {
|
||||
newSchema := &subSchema{parent: currentSchema, property: KEY_ITEMS}
|
||||
newSchema.ref = currentSchema.ref
|
||||
currentSchema.AddItemsChild(newSchema)
|
||||
@ -395,7 +483,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
||||
},
|
||||
))
|
||||
}
|
||||
if *multipleOfValue <= 0 {
|
||||
if multipleOfValue.Cmp(big.NewFloat(0)) <= 0 {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.GreaterThanZero(),
|
||||
ErrorDetails{"number": KEY_MULTIPLE_OF},
|
||||
@ -425,10 +513,15 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
||||
}
|
||||
exclusiveMinimumValue := m[KEY_EXCLUSIVE_MINIMUM].(bool)
|
||||
currentSchema.exclusiveMinimum = exclusiveMinimumValue
|
||||
} else if isJsonNumber(m[KEY_EXCLUSIVE_MINIMUM]) {
|
||||
minimumValue := mustBeNumber(m[KEY_EXCLUSIVE_MINIMUM])
|
||||
|
||||
currentSchema.minimum = minimumValue
|
||||
currentSchema.exclusiveMinimum = true
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.MustBeOfA(),
|
||||
ErrorDetails{"x": KEY_EXCLUSIVE_MINIMUM, "y": TYPE_BOOLEAN},
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{"expected": TYPE_BOOLEAN + ", " + TYPE_NUMBER, "given": KEY_EXCLUSIVE_MINIMUM},
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -454,16 +547,21 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
||||
}
|
||||
exclusiveMaximumValue := m[KEY_EXCLUSIVE_MAXIMUM].(bool)
|
||||
currentSchema.exclusiveMaximum = exclusiveMaximumValue
|
||||
} else if isJsonNumber(m[KEY_EXCLUSIVE_MAXIMUM]) {
|
||||
maximumValue := mustBeNumber(m[KEY_EXCLUSIVE_MAXIMUM])
|
||||
|
||||
currentSchema.maximum = maximumValue
|
||||
currentSchema.exclusiveMaximum = true
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.MustBeOfA(),
|
||||
ErrorDetails{"x": KEY_EXCLUSIVE_MAXIMUM, "y": STRING_NUMBER},
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{"expected": TYPE_BOOLEAN + ", " + TYPE_NUMBER, "given": KEY_EXCLUSIVE_MAXIMUM},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
if currentSchema.minimum != nil && currentSchema.maximum != nil {
|
||||
if *currentSchema.minimum > *currentSchema.maximum {
|
||||
if currentSchema.minimum.Cmp(currentSchema.maximum) == 1 {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.CannotBeGT(),
|
||||
ErrorDetails{"x": KEY_MINIMUM, "y": KEY_MAXIMUM},
|
||||
@ -538,11 +636,6 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
||||
formatString, ok := m[KEY_FORMAT].(string)
|
||||
if ok && FormatCheckers.Has(formatString) {
|
||||
currentSchema.format = formatString
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.MustBeValidFormat(),
|
||||
ErrorDetails{"key": KEY_FORMAT, "given": m[KEY_FORMAT]},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -662,8 +755,24 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
||||
}
|
||||
}
|
||||
|
||||
if existsMapKey(m, KEY_CONTAINS) {
|
||||
newSchema := &subSchema{property: KEY_CONTAINS, parent: currentSchema, ref: currentSchema.ref}
|
||||
currentSchema.contains = newSchema
|
||||
err := d.parseSchema(m[KEY_CONTAINS], newSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// validation : all
|
||||
|
||||
if existsMapKey(m, KEY_CONST) {
|
||||
err := currentSchema.AddConst(m[KEY_CONST])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if existsMapKey(m, KEY_ENUM) {
|
||||
if isKind(m[KEY_ENUM], reflect.Slice) {
|
||||
for _, v := range m[KEY_ENUM].([]interface{}) {
|
||||
@ -737,7 +846,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
||||
}
|
||||
|
||||
if existsMapKey(m, KEY_NOT) {
|
||||
if isKind(m[KEY_NOT], reflect.Map) {
|
||||
if isKind(m[KEY_NOT], reflect.Map, reflect.Bool) {
|
||||
newSchema := &subSchema{property: KEY_NOT, parent: currentSchema, ref: currentSchema.ref}
|
||||
currentSchema.SetNot(newSchema)
|
||||
err := d.parseSchema(m[KEY_NOT], newSchema)
|
||||
@ -752,71 +861,88 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
||||
}
|
||||
}
|
||||
|
||||
if existsMapKey(m, KEY_IF) {
|
||||
if isKind(m[KEY_IF], reflect.Map, reflect.Bool) {
|
||||
newSchema := &subSchema{property: KEY_IF, parent: currentSchema, ref: currentSchema.ref}
|
||||
currentSchema.SetIf(newSchema)
|
||||
err := d.parseSchema(m[KEY_IF], newSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.MustBeOfAn(),
|
||||
ErrorDetails{"x": KEY_IF, "y": TYPE_OBJECT},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
if existsMapKey(m, KEY_THEN) {
|
||||
if isKind(m[KEY_THEN], reflect.Map, reflect.Bool) {
|
||||
newSchema := &subSchema{property: KEY_THEN, parent: currentSchema, ref: currentSchema.ref}
|
||||
currentSchema.SetThen(newSchema)
|
||||
err := d.parseSchema(m[KEY_THEN], newSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.MustBeOfAn(),
|
||||
ErrorDetails{"x": KEY_THEN, "y": TYPE_OBJECT},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
if existsMapKey(m, KEY_ELSE) {
|
||||
if isKind(m[KEY_ELSE], reflect.Map, reflect.Bool) {
|
||||
newSchema := &subSchema{property: KEY_ELSE, parent: currentSchema, ref: currentSchema.ref}
|
||||
currentSchema.SetElse(newSchema)
|
||||
err := d.parseSchema(m[KEY_ELSE], newSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.MustBeOfAn(),
|
||||
ErrorDetails{"x": KEY_ELSE, "y": TYPE_OBJECT},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Schema) parseReference(documentNode interface{}, currentSchema *subSchema, reference string) (e error) {
|
||||
func (d *Schema) parseReference(documentNode interface{}, currentSchema *subSchema) error {
|
||||
var (
|
||||
refdDocumentNode interface{}
|
||||
dsp *schemaPoolDocument
|
||||
err error
|
||||
)
|
||||
|
||||
var err error
|
||||
newSchema := &subSchema{property: KEY_REF, parent: currentSchema, ref: currentSchema.ref}
|
||||
|
||||
d.referencePool.Add(currentSchema.ref.String(), newSchema)
|
||||
|
||||
dsp, err = d.pool.GetDocument(*currentSchema.ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newSchema.id = currentSchema.ref
|
||||
|
||||
refdDocumentNode = dsp.Document
|
||||
|
||||
jsonReference, err := gojsonreference.NewJsonReference(reference)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
standaloneDocument := d.pool.GetStandaloneDocument()
|
||||
|
||||
if jsonReference.HasFullUrl {
|
||||
currentSchema.ref = &jsonReference
|
||||
} else {
|
||||
inheritedReference, err := currentSchema.ref.Inherits(jsonReference)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currentSchema.ref = inheritedReference
|
||||
}
|
||||
|
||||
jsonPointer := currentSchema.ref.GetPointer()
|
||||
|
||||
var refdDocumentNode interface{}
|
||||
|
||||
if standaloneDocument != nil {
|
||||
|
||||
var err error
|
||||
refdDocumentNode, _, err = jsonPointer.Get(standaloneDocument)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
var err error
|
||||
dsp, err := d.pool.GetDocument(*currentSchema.ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
refdDocumentNode, _, err = jsonPointer.Get(dsp.Document)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if !isKind(refdDocumentNode, reflect.Map) {
|
||||
if !isKind(refdDocumentNode, reflect.Map, reflect.Bool) {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.MustBeOfType(),
|
||||
ErrorDetails{"key": STRING_SCHEMA, "type": TYPE_OBJECT},
|
||||
))
|
||||
}
|
||||
|
||||
// returns the loaded referenced subSchema for the caller to update its current subSchema
|
||||
newSchemaDocument := refdDocumentNode.(map[string]interface{})
|
||||
|
||||
newSchema := &subSchema{property: KEY_REF, parent: currentSchema, ref: currentSchema.ref}
|
||||
d.referencePool.Add(currentSchema.ref.String()+reference, newSchema)
|
||||
|
||||
err = d.parseSchema(newSchemaDocument, newSchema)
|
||||
err = d.parseSchema(refdDocumentNode, newSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -884,7 +1010,7 @@ func (d *Schema) parseDependencies(documentNode interface{}, currentSchema *subS
|
||||
currentSchema.dependencies[k] = valuesToRegister
|
||||
}
|
||||
|
||||
case reflect.Map:
|
||||
case reflect.Map, reflect.Bool:
|
||||
depSchema := &subSchema{property: k, parent: currentSchema, ref: currentSchema.ref}
|
||||
err := d.parseSchema(m[k], depSchema)
|
||||
if err != nil {
|
||||
|
153
vendor/github.com/xeipuuv/gojsonschema/schemaPool.go
generated
vendored
153
vendor/github.com/xeipuuv/gojsonschema/schemaPool.go
generated
vendored
@ -28,6 +28,7 @@ package gojsonschema
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
|
||||
"github.com/xeipuuv/gojsonreference"
|
||||
)
|
||||
@ -38,70 +39,154 @@ type schemaPoolDocument struct {
|
||||
|
||||
type schemaPool struct {
|
||||
schemaPoolDocuments map[string]*schemaPoolDocument
|
||||
standaloneDocument interface{}
|
||||
jsonLoaderFactory JSONLoaderFactory
|
||||
}
|
||||
|
||||
func newSchemaPool() *schemaPool {
|
||||
func newSchemaPool(f JSONLoaderFactory) *schemaPool {
|
||||
|
||||
p := &schemaPool{}
|
||||
p.schemaPoolDocuments = make(map[string]*schemaPoolDocument)
|
||||
p.standaloneDocument = nil
|
||||
p.jsonLoaderFactory = f
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *schemaPool) SetStandaloneDocument(document interface{}) {
|
||||
p.standaloneDocument = document
|
||||
func (p *schemaPool) ParseReferences(document interface{}, ref gojsonreference.JsonReference) {
|
||||
// Only the root document should be added to the schema pool
|
||||
p.schemaPoolDocuments[ref.String()] = &schemaPoolDocument{Document: document}
|
||||
p.parseReferencesRecursive(document, ref)
|
||||
}
|
||||
|
||||
func (p *schemaPool) GetStandaloneDocument() (document interface{}) {
|
||||
return p.standaloneDocument
|
||||
func (p *schemaPool) parseReferencesRecursive(document interface{}, ref gojsonreference.JsonReference) {
|
||||
// parseReferencesRecursive parses a JSON document and resolves all $id and $ref references.
|
||||
// For $ref references it takes into account the $id scope it is in and replaces
|
||||
// the reference by the absolute resolved reference
|
||||
|
||||
// When encountering errors it fails silently. Error handling is done when the schema
|
||||
// is syntactically parsed and any error encountered here should also come up there.
|
||||
switch m := document.(type) {
|
||||
case []interface{}:
|
||||
for _, v := range m {
|
||||
p.parseReferencesRecursive(v, ref)
|
||||
}
|
||||
case map[string]interface{}:
|
||||
localRef := &ref
|
||||
|
||||
keyID := KEY_ID_NEW
|
||||
if existsMapKey(m, KEY_ID) {
|
||||
keyID = KEY_ID
|
||||
}
|
||||
if existsMapKey(m, keyID) && isKind(m[keyID], reflect.String) {
|
||||
jsonReference, err := gojsonreference.NewJsonReference(m[keyID].(string))
|
||||
if err == nil {
|
||||
localRef, err = ref.Inherits(jsonReference)
|
||||
if err == nil {
|
||||
p.schemaPoolDocuments[localRef.String()] = &schemaPoolDocument{Document: document}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if existsMapKey(m, KEY_REF) && isKind(m[KEY_REF], reflect.String) {
|
||||
jsonReference, err := gojsonreference.NewJsonReference(m[KEY_REF].(string))
|
||||
if err == nil {
|
||||
absoluteRef, err := localRef.Inherits(jsonReference)
|
||||
if err == nil {
|
||||
m[KEY_REF] = absoluteRef.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k, v := range m {
|
||||
// const and enums should be interpreted literally, so ignore them
|
||||
if k == KEY_CONST || k == KEY_ENUM {
|
||||
continue
|
||||
}
|
||||
// Something like a property or a dependency is not a valid schema, as it might describe properties named "$ref", "$id" or "const", etc
|
||||
// Therefore don't treat it like a schema.
|
||||
if k == KEY_PROPERTIES || k == KEY_DEPENDENCIES || k == KEY_PATTERN_PROPERTIES {
|
||||
if child, ok := v.(map[string]interface{}); ok {
|
||||
for _, v := range child {
|
||||
p.parseReferencesRecursive(v, *localRef)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p.parseReferencesRecursive(v, *localRef)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *schemaPool) GetDocument(reference gojsonreference.JsonReference) (*schemaPoolDocument, error) {
|
||||
|
||||
var (
|
||||
spd *schemaPoolDocument
|
||||
ok bool
|
||||
err error
|
||||
)
|
||||
|
||||
if internalLogEnabled {
|
||||
internalLog("Get Document ( %s )", reference.String())
|
||||
}
|
||||
|
||||
var err error
|
||||
// Create a deep copy, so we can remove the fragment part later on without altering the original
|
||||
refToUrl, _ := gojsonreference.NewJsonReference(reference.String())
|
||||
|
||||
// It is not possible to load anything that is not canonical...
|
||||
if !reference.IsCanonical() {
|
||||
return nil, errors.New(formatErrorDescription(
|
||||
Locale.ReferenceMustBeCanonical(),
|
||||
ErrorDetails{"reference": reference},
|
||||
))
|
||||
}
|
||||
// First check if the given fragment is a location independent identifier
|
||||
// http://json-schema.org/latest/json-schema-core.html#rfc.section.8.2.3
|
||||
|
||||
refToUrl := reference
|
||||
refToUrl.GetUrl().Fragment = ""
|
||||
|
||||
var spd *schemaPoolDocument
|
||||
|
||||
// Try to find the requested document in the pool
|
||||
for k := range p.schemaPoolDocuments {
|
||||
if k == refToUrl.String() {
|
||||
spd = p.schemaPoolDocuments[k]
|
||||
}
|
||||
}
|
||||
|
||||
if spd != nil {
|
||||
if spd, ok = p.schemaPoolDocuments[refToUrl.String()]; ok {
|
||||
if internalLogEnabled {
|
||||
internalLog(" From pool")
|
||||
}
|
||||
return spd, nil
|
||||
}
|
||||
|
||||
jsonReferenceLoader := NewReferenceLoader(reference.String())
|
||||
document, err := jsonReferenceLoader.loadJSON()
|
||||
// If the given reference is not a location independent identifier,
|
||||
// strip the fragment and look for a document with it's base URI
|
||||
|
||||
refToUrl.GetUrl().Fragment = ""
|
||||
|
||||
if cachedSpd, ok := p.schemaPoolDocuments[refToUrl.String()]; ok {
|
||||
document, _, err := reference.GetPointer().Get(cachedSpd.Document)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if internalLogEnabled {
|
||||
internalLog(" From pool")
|
||||
}
|
||||
|
||||
spd = &schemaPoolDocument{Document: document}
|
||||
p.schemaPoolDocuments[reference.String()] = spd
|
||||
|
||||
return spd, nil
|
||||
}
|
||||
|
||||
// It is not possible to load anything remotely that is not canonical...
|
||||
if !reference.IsCanonical() {
|
||||
return nil, errors.New(formatErrorDescription(
|
||||
Locale.ReferenceMustBeCanonical(),
|
||||
ErrorDetails{"reference": reference.String()},
|
||||
))
|
||||
}
|
||||
|
||||
jsonReferenceLoader := p.jsonLoaderFactory.New(reference.String())
|
||||
document, err := jsonReferenceLoader.LoadJSON()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
spd = &schemaPoolDocument{Document: document}
|
||||
// add the document to the pool for potential later use
|
||||
p.schemaPoolDocuments[refToUrl.String()] = spd
|
||||
// add the whole document to the pool for potential re-use
|
||||
p.ParseReferences(document, refToUrl)
|
||||
|
||||
return spd, nil
|
||||
// resolve the potential fragment and also cache it
|
||||
document, _, err = reference.GetPointer().Get(document)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &schemaPoolDocument{Document: document}, nil
|
||||
}
|
||||
|
5
vendor/github.com/xeipuuv/gojsonschema/schemaReferencePool.go
generated
vendored
5
vendor/github.com/xeipuuv/gojsonschema/schemaReferencePool.go
generated
vendored
@ -62,6 +62,7 @@ func (p *schemaReferencePool) Add(ref string, sch *subSchema) {
|
||||
if internalLogEnabled {
|
||||
internalLog(fmt.Sprintf("Add Schema Reference %s to pool", ref))
|
||||
}
|
||||
|
||||
p.documents[ref] = sch
|
||||
if _, ok := p.documents[ref]; !ok {
|
||||
p.documents[ref] = sch
|
||||
}
|
||||
}
|
||||
|
2
vendor/github.com/xeipuuv/gojsonschema/schemaType.go
generated
vendored
2
vendor/github.com/xeipuuv/gojsonschema/schemaType.go
generated
vendored
@ -44,7 +44,7 @@ func (t *jsonSchemaType) IsTyped() bool {
|
||||
func (t *jsonSchemaType) Add(etype string) error {
|
||||
|
||||
if !isStringInSlice(JSON_TYPES, etype) {
|
||||
return errors.New(formatErrorDescription(Locale.NotAValidType(), ErrorDetails{"type": etype}))
|
||||
return errors.New(formatErrorDescription(Locale.NotAValidType(), ErrorDetails{"given": "/" + etype + "/", "expected": JSON_TYPES}))
|
||||
}
|
||||
|
||||
if t.Contains(etype) {
|
||||
|
64
vendor/github.com/xeipuuv/gojsonschema/subSchema.go
generated
vendored
64
vendor/github.com/xeipuuv/gojsonschema/subSchema.go
generated
vendored
@ -28,6 +28,7 @@ package gojsonschema
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
@ -35,8 +36,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
KEY_SCHEMA = "$subSchema"
|
||||
KEY_ID = "$id"
|
||||
KEY_SCHEMA = "$schema"
|
||||
KEY_ID = "id"
|
||||
KEY_ID_NEW = "$id"
|
||||
KEY_REF = "$ref"
|
||||
KEY_TITLE = "title"
|
||||
KEY_DESCRIPTION = "description"
|
||||
@ -46,6 +48,7 @@ const (
|
||||
KEY_PROPERTIES = "properties"
|
||||
KEY_PATTERN_PROPERTIES = "patternProperties"
|
||||
KEY_ADDITIONAL_PROPERTIES = "additionalProperties"
|
||||
KEY_PROPERTY_NAMES = "propertyNames"
|
||||
KEY_DEFINITIONS = "definitions"
|
||||
KEY_MULTIPLE_OF = "multipleOf"
|
||||
KEY_MINIMUM = "minimum"
|
||||
@ -63,17 +66,22 @@ const (
|
||||
KEY_MIN_ITEMS = "minItems"
|
||||
KEY_MAX_ITEMS = "maxItems"
|
||||
KEY_UNIQUE_ITEMS = "uniqueItems"
|
||||
KEY_CONTAINS = "contains"
|
||||
KEY_CONST = "const"
|
||||
KEY_ENUM = "enum"
|
||||
KEY_ONE_OF = "oneOf"
|
||||
KEY_ANY_OF = "anyOf"
|
||||
KEY_ALL_OF = "allOf"
|
||||
KEY_NOT = "not"
|
||||
KEY_IF = "if"
|
||||
KEY_THEN = "then"
|
||||
KEY_ELSE = "else"
|
||||
)
|
||||
|
||||
type subSchema struct {
|
||||
|
||||
// basic subSchema meta properties
|
||||
id *string
|
||||
id *gojsonreference.JsonReference
|
||||
title *string
|
||||
description *string
|
||||
|
||||
@ -86,22 +94,18 @@ type subSchema struct {
|
||||
ref *gojsonreference.JsonReference
|
||||
// Schema referenced
|
||||
refSchema *subSchema
|
||||
// Json reference
|
||||
subSchema *gojsonreference.JsonReference
|
||||
|
||||
// hierarchy
|
||||
parent *subSchema
|
||||
definitions map[string]*subSchema
|
||||
definitionsChildren []*subSchema
|
||||
itemsChildren []*subSchema
|
||||
itemsChildrenIsSingleSchema bool
|
||||
propertiesChildren []*subSchema
|
||||
|
||||
// validation : number / integer
|
||||
multipleOf *float64
|
||||
maximum *float64
|
||||
multipleOf *big.Float
|
||||
maximum *big.Float
|
||||
exclusiveMaximum bool
|
||||
minimum *float64
|
||||
minimum *big.Float
|
||||
exclusiveMinimum bool
|
||||
|
||||
// validation : string
|
||||
@ -118,27 +122,43 @@ type subSchema struct {
|
||||
dependencies map[string]interface{}
|
||||
additionalProperties interface{}
|
||||
patternProperties map[string]*subSchema
|
||||
propertyNames *subSchema
|
||||
|
||||
// validation : array
|
||||
minItems *int
|
||||
maxItems *int
|
||||
uniqueItems bool
|
||||
contains *subSchema
|
||||
|
||||
additionalItems interface{}
|
||||
|
||||
// validation : all
|
||||
enum []string
|
||||
_const *string //const is a golang keyword
|
||||
enum []string
|
||||
|
||||
// validation : subSchema
|
||||
oneOf []*subSchema
|
||||
anyOf []*subSchema
|
||||
allOf []*subSchema
|
||||
not *subSchema
|
||||
_if *subSchema // if/else are golang keywords
|
||||
_then *subSchema
|
||||
_else *subSchema
|
||||
}
|
||||
|
||||
func (s *subSchema) AddConst(i interface{}) error {
|
||||
|
||||
is, err := marshalWithoutNumber(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s._const = is
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *subSchema) AddEnum(i interface{}) error {
|
||||
|
||||
is, err := marshalToJsonString(i)
|
||||
is, err := marshalWithoutNumber(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -157,7 +177,7 @@ func (s *subSchema) AddEnum(i interface{}) error {
|
||||
|
||||
func (s *subSchema) ContainsEnum(i interface{}) (bool, error) {
|
||||
|
||||
is, err := marshalToJsonString(i)
|
||||
is, err := marshalWithoutNumber(i)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@ -181,6 +201,18 @@ func (s *subSchema) SetNot(subSchema *subSchema) {
|
||||
s.not = subSchema
|
||||
}
|
||||
|
||||
func (s *subSchema) SetIf(subSchema *subSchema) {
|
||||
s._if = subSchema
|
||||
}
|
||||
|
||||
func (s *subSchema) SetThen(subSchema *subSchema) {
|
||||
s._then = subSchema
|
||||
}
|
||||
|
||||
func (s *subSchema) SetElse(subSchema *subSchema) {
|
||||
s._else = subSchema
|
||||
}
|
||||
|
||||
func (s *subSchema) AddRequired(value string) error {
|
||||
|
||||
if isStringInSlice(s.required, value) {
|
||||
@ -195,10 +227,6 @@ func (s *subSchema) AddRequired(value string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *subSchema) AddDefinitionChild(child *subSchema) {
|
||||
s.definitionsChildren = append(s.definitionsChildren, child)
|
||||
}
|
||||
|
||||
func (s *subSchema) AddItemsChild(child *subSchema) {
|
||||
s.itemsChildren = append(s.itemsChildren, child)
|
||||
}
|
||||
@ -214,7 +242,7 @@ func (s *subSchema) PatternPropertiesString() string {
|
||||
}
|
||||
|
||||
patternPropertiesKeySlice := []string{}
|
||||
for pk, _ := range s.patternProperties {
|
||||
for pk := range s.patternProperties {
|
||||
patternPropertiesKeySlice = append(patternPropertiesKeySlice, `"`+pk+`"`)
|
||||
}
|
||||
|
||||
|
66
vendor/github.com/xeipuuv/gojsonschema/utils.go
generated
vendored
66
vendor/github.com/xeipuuv/gojsonschema/utils.go
generated
vendored
@ -29,12 +29,23 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func isKind(what interface{}, kind reflect.Kind) bool {
|
||||
return reflect.ValueOf(what).Kind() == kind
|
||||
func isKind(what interface{}, kinds ...reflect.Kind) bool {
|
||||
target := what
|
||||
if isJsonNumber(what) {
|
||||
// JSON Numbers are strings!
|
||||
target = *mustBeNumber(what)
|
||||
}
|
||||
targetKind := reflect.ValueOf(target).Kind()
|
||||
for _, kind := range kinds {
|
||||
if targetKind == kind {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func existsMapKey(m map[string]interface{}, k string) bool {
|
||||
@ -62,6 +73,28 @@ func marshalToJsonString(value interface{}) (*string, error) {
|
||||
return &sBytes, nil
|
||||
}
|
||||
|
||||
func marshalWithoutNumber(value interface{}) (*string, error) {
|
||||
|
||||
// The JSON is decoded using https://golang.org/pkg/encoding/json/#Decoder.UseNumber
|
||||
// This means the numbers are internally still represented as strings and therefore 1.00 is unequal to 1
|
||||
// One way to eliminate these differences is to decode and encode the JSON one more time without Decoder.UseNumber
|
||||
// so that these differences in representation are removed
|
||||
|
||||
jsonString, err := marshalToJsonString(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var document interface{}
|
||||
|
||||
err = json.Unmarshal([]byte(*jsonString), &document)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return marshalToJsonString(document)
|
||||
}
|
||||
|
||||
func isJsonNumber(what interface{}) bool {
|
||||
|
||||
switch what.(type) {
|
||||
@ -73,20 +106,13 @@ func isJsonNumber(what interface{}) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func checkJsonNumber(what interface{}) (isValidFloat64 bool, isValidInt64 bool, isValidInt32 bool) {
|
||||
func checkJsonInteger(what interface{}) (isInt bool) {
|
||||
|
||||
jsonNumber := what.(json.Number)
|
||||
|
||||
_, errFloat64 := jsonNumber.Float64()
|
||||
_, errInt64 := jsonNumber.Int64()
|
||||
bigFloat, isValidNumber := new(big.Float).SetString(string(jsonNumber))
|
||||
|
||||
isValidFloat64 = errFloat64 == nil
|
||||
isValidInt64 = errInt64 == nil
|
||||
|
||||
_, errInt32 := strconv.ParseInt(jsonNumber.String(), 10, 32)
|
||||
isValidInt32 = isValidInt64 && errInt32 == nil
|
||||
|
||||
return
|
||||
return isValidNumber && bigFloat.IsInt()
|
||||
|
||||
}
|
||||
|
||||
@ -111,9 +137,9 @@ func mustBeInteger(what interface{}) *int {
|
||||
|
||||
number := what.(json.Number)
|
||||
|
||||
_, _, isValidInt32 := checkJsonNumber(number)
|
||||
isInt := checkJsonInteger(number)
|
||||
|
||||
if isValidInt32 {
|
||||
if isInt {
|
||||
|
||||
int64Value, err := number.Int64()
|
||||
if err != nil {
|
||||
@ -132,15 +158,13 @@ func mustBeInteger(what interface{}) *int {
|
||||
return nil
|
||||
}
|
||||
|
||||
func mustBeNumber(what interface{}) *float64 {
|
||||
func mustBeNumber(what interface{}) *big.Float {
|
||||
|
||||
if isJsonNumber(what) {
|
||||
|
||||
number := what.(json.Number)
|
||||
float64Value, err := number.Float64()
|
||||
|
||||
if err == nil {
|
||||
return &float64Value
|
||||
float64Value, success := new(big.Float).SetString(string(number))
|
||||
if success {
|
||||
return float64Value
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
261
vendor/github.com/xeipuuv/gojsonschema/validation.go
generated
vendored
261
vendor/github.com/xeipuuv/gojsonschema/validation.go
generated
vendored
@ -27,6 +27,7 @@ package gojsonschema
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@ -55,29 +56,32 @@ func (v *Schema) Validate(l JSONLoader) (*Result, error) {
|
||||
|
||||
// load document
|
||||
|
||||
root, err := l.loadJSON()
|
||||
root, err := l.LoadJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return v.validateDocument(root), nil
|
||||
}
|
||||
|
||||
func (v *Schema) validateDocument(root interface{}) *Result {
|
||||
// begin validation
|
||||
|
||||
result := &Result{}
|
||||
context := newJsonContext(STRING_CONTEXT_ROOT, nil)
|
||||
context := NewJsonContext(STRING_CONTEXT_ROOT, nil)
|
||||
v.rootSchema.validateRecursive(v.rootSchema, root, result, context)
|
||||
|
||||
return result, nil
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *subSchema) subValidateWithContext(document interface{}, context *jsonContext) *Result {
|
||||
func (v *subSchema) subValidateWithContext(document interface{}, context *JsonContext) *Result {
|
||||
result := &Result{}
|
||||
v.validateRecursive(v, document, result, context)
|
||||
return result
|
||||
}
|
||||
|
||||
// Walker function to validate the json recursively against the subSchema
|
||||
func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode interface{}, result *Result, context *jsonContext) {
|
||||
func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode interface{}, result *Result, context *JsonContext) {
|
||||
|
||||
if internalLogEnabled {
|
||||
internalLog("validateRecursive %s", context.String())
|
||||
@ -93,7 +97,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i
|
||||
// Check for null value
|
||||
if currentNode == nil {
|
||||
if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_NULL) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(InvalidTypeError),
|
||||
context,
|
||||
currentNode,
|
||||
@ -114,18 +118,18 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i
|
||||
|
||||
value := currentNode.(json.Number)
|
||||
|
||||
_, isValidInt64, _ := checkJsonNumber(value)
|
||||
isInt := checkJsonInteger(value)
|
||||
|
||||
validType := currentSubSchema.types.Contains(TYPE_NUMBER) || (isValidInt64 && currentSubSchema.types.Contains(TYPE_INTEGER))
|
||||
validType := currentSubSchema.types.Contains(TYPE_NUMBER) || (isInt && currentSubSchema.types.Contains(TYPE_INTEGER))
|
||||
|
||||
if currentSubSchema.types.IsTyped() && !validType {
|
||||
|
||||
givenType := TYPE_INTEGER
|
||||
if !isValidInt64 {
|
||||
if !isInt {
|
||||
givenType = TYPE_NUMBER
|
||||
}
|
||||
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(InvalidTypeError),
|
||||
context,
|
||||
currentNode,
|
||||
@ -154,7 +158,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i
|
||||
case reflect.Slice:
|
||||
|
||||
if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_ARRAY) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(InvalidTypeError),
|
||||
context,
|
||||
currentNode,
|
||||
@ -177,7 +181,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i
|
||||
|
||||
case reflect.Map:
|
||||
if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_OBJECT) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(InvalidTypeError),
|
||||
context,
|
||||
currentNode,
|
||||
@ -202,7 +206,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i
|
||||
for _, pSchema := range currentSubSchema.propertiesChildren {
|
||||
nextNode, ok := castCurrentNode[pSchema.property]
|
||||
if ok {
|
||||
subContext := newJsonContext(pSchema.property, context)
|
||||
subContext := NewJsonContext(pSchema.property, context)
|
||||
v.validateRecursive(pSchema, nextNode, result, subContext)
|
||||
}
|
||||
}
|
||||
@ -212,7 +216,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i
|
||||
case reflect.Bool:
|
||||
|
||||
if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_BOOLEAN) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(InvalidTypeError),
|
||||
context,
|
||||
currentNode,
|
||||
@ -234,7 +238,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i
|
||||
case reflect.String:
|
||||
|
||||
if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_STRING) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(InvalidTypeError),
|
||||
context,
|
||||
currentNode,
|
||||
@ -263,7 +267,7 @@ func (v *subSchema) validateRecursive(currentSubSchema *subSchema, currentNode i
|
||||
}
|
||||
|
||||
// Different kinds of validation there, subSchema / common / array / object / string...
|
||||
func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode interface{}, result *Result, context *jsonContext) {
|
||||
func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode interface{}, result *Result, context *JsonContext) {
|
||||
|
||||
if internalLogEnabled {
|
||||
internalLog("validateSchema %s", context.String())
|
||||
@ -287,7 +291,7 @@ func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode inte
|
||||
}
|
||||
if !validatedAnyOf {
|
||||
|
||||
result.addError(new(NumberAnyOfError), context, currentNode, ErrorDetails{})
|
||||
result.addInternalError(new(NumberAnyOfError), context, currentNode, ErrorDetails{})
|
||||
|
||||
if bestValidationResult != nil {
|
||||
// add error messages of closest matching subSchema as
|
||||
@ -313,7 +317,7 @@ func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode inte
|
||||
|
||||
if nbValidated != 1 {
|
||||
|
||||
result.addError(new(NumberOneOfError), context, currentNode, ErrorDetails{})
|
||||
result.addInternalError(new(NumberOneOfError), context, currentNode, ErrorDetails{})
|
||||
|
||||
if nbValidated == 0 {
|
||||
// add error messages of closest matching subSchema as
|
||||
@ -336,14 +340,14 @@ func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode inte
|
||||
}
|
||||
|
||||
if nbValidated != len(currentSubSchema.allOf) {
|
||||
result.addError(new(NumberAllOfError), context, currentNode, ErrorDetails{})
|
||||
result.addInternalError(new(NumberAllOfError), context, currentNode, ErrorDetails{})
|
||||
}
|
||||
}
|
||||
|
||||
if currentSubSchema.not != nil {
|
||||
validationResult := currentSubSchema.not.subValidateWithContext(currentNode, context)
|
||||
if validationResult.Valid() {
|
||||
result.addError(new(NumberNotError), context, currentNode, ErrorDetails{})
|
||||
result.addInternalError(new(NumberNotError), context, currentNode, ErrorDetails{})
|
||||
}
|
||||
}
|
||||
|
||||
@ -356,7 +360,7 @@ func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode inte
|
||||
case []string:
|
||||
for _, dependOnKey := range dependency {
|
||||
if _, dependencyResolved := currentNode.(map[string]interface{})[dependOnKey]; !dependencyResolved {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(MissingDependencyError),
|
||||
context,
|
||||
currentNode,
|
||||
@ -367,31 +371,65 @@ func (v *subSchema) validateSchema(currentSubSchema *subSchema, currentNode inte
|
||||
|
||||
case *subSchema:
|
||||
dependency.validateRecursive(dependency, currentNode, result, context)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if currentSubSchema._if != nil {
|
||||
validationResultIf := currentSubSchema._if.subValidateWithContext(currentNode, context)
|
||||
if currentSubSchema._then != nil && validationResultIf.Valid() {
|
||||
validationResultThen := currentSubSchema._then.subValidateWithContext(currentNode, context)
|
||||
if !validationResultThen.Valid() {
|
||||
result.addInternalError(new(ConditionThenError), context, currentNode, ErrorDetails{})
|
||||
result.mergeErrors(validationResultThen)
|
||||
}
|
||||
}
|
||||
if currentSubSchema._else != nil && !validationResultIf.Valid() {
|
||||
validationResultElse := currentSubSchema._else.subValidateWithContext(currentNode, context)
|
||||
if !validationResultElse.Valid() {
|
||||
result.addInternalError(new(ConditionElseError), context, currentNode, ErrorDetails{})
|
||||
result.mergeErrors(validationResultElse)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.incrementScore()
|
||||
}
|
||||
|
||||
func (v *subSchema) validateCommon(currentSubSchema *subSchema, value interface{}, result *Result, context *jsonContext) {
|
||||
func (v *subSchema) validateCommon(currentSubSchema *subSchema, value interface{}, result *Result, context *JsonContext) {
|
||||
|
||||
if internalLogEnabled {
|
||||
internalLog("validateCommon %s", context.String())
|
||||
internalLog(" %v", value)
|
||||
}
|
||||
|
||||
// const:
|
||||
if currentSubSchema._const != nil {
|
||||
vString, err := marshalWithoutNumber(value)
|
||||
if err != nil {
|
||||
result.addInternalError(new(InternalError), context, value, ErrorDetails{"error": err})
|
||||
}
|
||||
if *vString != *currentSubSchema._const {
|
||||
result.addInternalError(new(ConstError),
|
||||
context,
|
||||
value,
|
||||
ErrorDetails{
|
||||
"allowed": *currentSubSchema._const,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// enum:
|
||||
if len(currentSubSchema.enum) > 0 {
|
||||
has, err := currentSubSchema.ContainsEnum(value)
|
||||
if err != nil {
|
||||
result.addError(new(InternalError), context, value, ErrorDetails{"error": err})
|
||||
result.addInternalError(new(InternalError), context, value, ErrorDetails{"error": err})
|
||||
}
|
||||
if !has {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(EnumError),
|
||||
context,
|
||||
value,
|
||||
@ -405,19 +443,19 @@ func (v *subSchema) validateCommon(currentSubSchema *subSchema, value interface{
|
||||
result.incrementScore()
|
||||
}
|
||||
|
||||
func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface{}, result *Result, context *jsonContext) {
|
||||
func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface{}, result *Result, context *JsonContext) {
|
||||
|
||||
if internalLogEnabled {
|
||||
internalLog("validateArray %s", context.String())
|
||||
internalLog(" %v", value)
|
||||
}
|
||||
|
||||
nbItems := len(value)
|
||||
nbValues := len(value)
|
||||
|
||||
// TODO explain
|
||||
if currentSubSchema.itemsChildrenIsSingleSchema {
|
||||
for i := range value {
|
||||
subContext := newJsonContext(strconv.Itoa(i), context)
|
||||
subContext := NewJsonContext(strconv.Itoa(i), context)
|
||||
validationResult := currentSubSchema.itemsChildren[0].subValidateWithContext(value[i], subContext)
|
||||
result.mergeErrors(validationResult)
|
||||
}
|
||||
@ -425,24 +463,27 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
|
||||
if currentSubSchema.itemsChildren != nil && len(currentSubSchema.itemsChildren) > 0 {
|
||||
|
||||
nbItems := len(currentSubSchema.itemsChildren)
|
||||
nbValues := len(value)
|
||||
|
||||
if nbItems == nbValues {
|
||||
for i := 0; i != nbItems; i++ {
|
||||
subContext := newJsonContext(strconv.Itoa(i), context)
|
||||
validationResult := currentSubSchema.itemsChildren[i].subValidateWithContext(value[i], subContext)
|
||||
result.mergeErrors(validationResult)
|
||||
}
|
||||
} else if nbItems < nbValues {
|
||||
// while we have both schemas and values, check them against each other
|
||||
for i := 0; i != nbItems && i != nbValues; i++ {
|
||||
subContext := NewJsonContext(strconv.Itoa(i), context)
|
||||
validationResult := currentSubSchema.itemsChildren[i].subValidateWithContext(value[i], subContext)
|
||||
result.mergeErrors(validationResult)
|
||||
}
|
||||
|
||||
if nbItems < nbValues {
|
||||
// we have less schemas than elements in the instance array,
|
||||
// but that might be ok if "additionalItems" is specified.
|
||||
|
||||
switch currentSubSchema.additionalItems.(type) {
|
||||
case bool:
|
||||
if !currentSubSchema.additionalItems.(bool) {
|
||||
result.addError(new(ArrayNoAdditionalItemsError), context, value, ErrorDetails{})
|
||||
result.addInternalError(new(ArrayNoAdditionalItemsError), context, value, ErrorDetails{})
|
||||
}
|
||||
case *subSchema:
|
||||
additionalItemSchema := currentSubSchema.additionalItems.(*subSchema)
|
||||
for i := nbItems; i != nbValues; i++ {
|
||||
subContext := newJsonContext(strconv.Itoa(i), context)
|
||||
subContext := NewJsonContext(strconv.Itoa(i), context)
|
||||
validationResult := additionalItemSchema.subValidateWithContext(value[i], subContext)
|
||||
result.mergeErrors(validationResult)
|
||||
}
|
||||
@ -453,8 +494,8 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
|
||||
|
||||
// minItems & maxItems
|
||||
if currentSubSchema.minItems != nil {
|
||||
if nbItems < int(*currentSubSchema.minItems) {
|
||||
result.addError(
|
||||
if nbValues < int(*currentSubSchema.minItems) {
|
||||
result.addInternalError(
|
||||
new(ArrayMinItemsError),
|
||||
context,
|
||||
value,
|
||||
@ -463,8 +504,8 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
|
||||
}
|
||||
}
|
||||
if currentSubSchema.maxItems != nil {
|
||||
if nbItems > int(*currentSubSchema.maxItems) {
|
||||
result.addError(
|
||||
if nbValues > int(*currentSubSchema.maxItems) {
|
||||
result.addInternalError(
|
||||
new(ArrayMaxItemsError),
|
||||
context,
|
||||
value,
|
||||
@ -477,12 +518,12 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
|
||||
if currentSubSchema.uniqueItems {
|
||||
var stringifiedItems []string
|
||||
for _, v := range value {
|
||||
vString, err := marshalToJsonString(v)
|
||||
vString, err := marshalWithoutNumber(v)
|
||||
if err != nil {
|
||||
result.addError(new(InternalError), context, value, ErrorDetails{"err": err})
|
||||
result.addInternalError(new(InternalError), context, value, ErrorDetails{"err": err})
|
||||
}
|
||||
if isStringInSlice(stringifiedItems, *vString) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(ItemsMustBeUniqueError),
|
||||
context,
|
||||
value,
|
||||
@ -493,10 +534,42 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
|
||||
}
|
||||
}
|
||||
|
||||
// contains:
|
||||
|
||||
if currentSubSchema.contains != nil {
|
||||
validatedOne := false
|
||||
var bestValidationResult *Result
|
||||
|
||||
for i, v := range value {
|
||||
subContext := NewJsonContext(strconv.Itoa(i), context)
|
||||
|
||||
validationResult := currentSubSchema.contains.subValidateWithContext(v, subContext)
|
||||
if validationResult.Valid() {
|
||||
validatedOne = true
|
||||
break
|
||||
} else {
|
||||
if bestValidationResult == nil || validationResult.score > bestValidationResult.score {
|
||||
bestValidationResult = validationResult
|
||||
}
|
||||
}
|
||||
}
|
||||
if !validatedOne {
|
||||
result.addInternalError(
|
||||
new(ArrayContainsError),
|
||||
context,
|
||||
value,
|
||||
ErrorDetails{},
|
||||
)
|
||||
if bestValidationResult != nil {
|
||||
result.mergeErrors(bestValidationResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.incrementScore()
|
||||
}
|
||||
|
||||
func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string]interface{}, result *Result, context *jsonContext) {
|
||||
func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string]interface{}, result *Result, context *JsonContext) {
|
||||
|
||||
if internalLogEnabled {
|
||||
internalLog("validateObject %s", context.String())
|
||||
@ -506,7 +579,7 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
|
||||
// minProperties & maxProperties:
|
||||
if currentSubSchema.minProperties != nil {
|
||||
if len(value) < int(*currentSubSchema.minProperties) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(ArrayMinPropertiesError),
|
||||
context,
|
||||
value,
|
||||
@ -516,7 +589,7 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
|
||||
}
|
||||
if currentSubSchema.maxProperties != nil {
|
||||
if len(value) > int(*currentSubSchema.maxProperties) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(ArrayMaxPropertiesError),
|
||||
context,
|
||||
value,
|
||||
@ -531,7 +604,7 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
|
||||
if ok {
|
||||
result.incrementScore()
|
||||
} else {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(RequiredError),
|
||||
context,
|
||||
value,
|
||||
@ -562,10 +635,10 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
|
||||
if found {
|
||||
|
||||
if pp_has && !pp_match {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(AdditionalPropertyNotAllowedError),
|
||||
context,
|
||||
value,
|
||||
value[pk],
|
||||
ErrorDetails{"property": pk},
|
||||
)
|
||||
}
|
||||
@ -573,10 +646,10 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
|
||||
} else {
|
||||
|
||||
if !pp_has || !pp_match {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(AdditionalPropertyNotAllowedError),
|
||||
context,
|
||||
value,
|
||||
value[pk],
|
||||
ErrorDetails{"property": pk},
|
||||
)
|
||||
}
|
||||
@ -625,10 +698,10 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
|
||||
|
||||
if pp_has && !pp_match {
|
||||
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(InvalidPropertyPatternError),
|
||||
context,
|
||||
value,
|
||||
value[pk],
|
||||
ErrorDetails{
|
||||
"property": pk,
|
||||
"pattern": currentSubSchema.PatternPropertiesString(),
|
||||
@ -639,10 +712,25 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
|
||||
}
|
||||
}
|
||||
|
||||
// propertyNames:
|
||||
if currentSubSchema.propertyNames != nil {
|
||||
for pk := range value {
|
||||
validationResult := currentSubSchema.propertyNames.subValidateWithContext(pk, context)
|
||||
if !validationResult.Valid() {
|
||||
result.addInternalError(new(InvalidPropertyNameError),
|
||||
context,
|
||||
value, ErrorDetails{
|
||||
"property": pk,
|
||||
})
|
||||
result.mergeErrors(validationResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.incrementScore()
|
||||
}
|
||||
|
||||
func (v *subSchema) validatePatternProperty(currentSubSchema *subSchema, key string, value interface{}, result *Result, context *jsonContext) (has bool, matched bool) {
|
||||
func (v *subSchema) validatePatternProperty(currentSubSchema *subSchema, key string, value interface{}, result *Result, context *JsonContext) (has bool, matched bool) {
|
||||
|
||||
if internalLogEnabled {
|
||||
internalLog("validatePatternProperty %s", context.String())
|
||||
@ -656,7 +744,7 @@ func (v *subSchema) validatePatternProperty(currentSubSchema *subSchema, key str
|
||||
for pk, pv := range currentSubSchema.patternProperties {
|
||||
if matches, _ := regexp.MatchString(pk, key); matches {
|
||||
has = true
|
||||
subContext := newJsonContext(key, context)
|
||||
subContext := NewJsonContext(key, context)
|
||||
validationResult := pv.subValidateWithContext(value, subContext)
|
||||
result.mergeErrors(validationResult)
|
||||
if validationResult.Valid() {
|
||||
@ -674,7 +762,7 @@ func (v *subSchema) validatePatternProperty(currentSubSchema *subSchema, key str
|
||||
return has, true
|
||||
}
|
||||
|
||||
func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{}, result *Result, context *jsonContext) {
|
||||
func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{}, result *Result, context *JsonContext) {
|
||||
|
||||
// Ignore JSON numbers
|
||||
if isJsonNumber(value) {
|
||||
@ -696,7 +784,7 @@ func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{
|
||||
// minLength & maxLength:
|
||||
if currentSubSchema.minLength != nil {
|
||||
if utf8.RuneCount([]byte(stringValue)) < int(*currentSubSchema.minLength) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(StringLengthGTEError),
|
||||
context,
|
||||
value,
|
||||
@ -706,7 +794,7 @@ func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{
|
||||
}
|
||||
if currentSubSchema.maxLength != nil {
|
||||
if utf8.RuneCount([]byte(stringValue)) > int(*currentSubSchema.maxLength) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(StringLengthLTEError),
|
||||
context,
|
||||
value,
|
||||
@ -718,7 +806,7 @@ func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{
|
||||
// pattern:
|
||||
if currentSubSchema.pattern != nil {
|
||||
if !currentSubSchema.pattern.MatchString(stringValue) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(DoesNotMatchPatternError),
|
||||
context,
|
||||
value,
|
||||
@ -731,7 +819,7 @@ func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{
|
||||
// format
|
||||
if currentSubSchema.format != "" {
|
||||
if !FormatCheckers.IsFormat(currentSubSchema.format, stringValue) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(DoesNotMatchFormatError),
|
||||
context,
|
||||
value,
|
||||
@ -743,7 +831,7 @@ func (v *subSchema) validateString(currentSubSchema *subSchema, value interface{
|
||||
result.incrementScore()
|
||||
}
|
||||
|
||||
func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{}, result *Result, context *jsonContext) {
|
||||
func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{}, result *Result, context *JsonContext) {
|
||||
|
||||
// Ignore non numbers
|
||||
if !isJsonNumber(value) {
|
||||
@ -756,17 +844,17 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{
|
||||
}
|
||||
|
||||
number := value.(json.Number)
|
||||
float64Value, _ := number.Float64()
|
||||
float64Value, _ := new(big.Float).SetString(string(number))
|
||||
|
||||
// multipleOf:
|
||||
if currentSubSchema.multipleOf != nil {
|
||||
|
||||
if !isFloat64AnInteger(float64Value / *currentSubSchema.multipleOf) {
|
||||
result.addError(
|
||||
if q := new(big.Float).Quo(float64Value, currentSubSchema.multipleOf); !q.IsInt() {
|
||||
result.addInternalError(
|
||||
new(MultipleOfError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{"multiple": *currentSubSchema.multipleOf},
|
||||
ErrorDetails{"multiple": currentSubSchema.multipleOf},
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -774,24 +862,24 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{
|
||||
//maximum & exclusiveMaximum:
|
||||
if currentSubSchema.maximum != nil {
|
||||
if currentSubSchema.exclusiveMaximum {
|
||||
if float64Value >= *currentSubSchema.maximum {
|
||||
result.addError(
|
||||
if float64Value.Cmp(currentSubSchema.maximum) >= 0 {
|
||||
result.addInternalError(
|
||||
new(NumberLTError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{
|
||||
"max": resultErrorFormatNumber(*currentSubSchema.maximum),
|
||||
"max": currentSubSchema.maximum,
|
||||
},
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if float64Value > *currentSubSchema.maximum {
|
||||
result.addError(
|
||||
if float64Value.Cmp(currentSubSchema.maximum) == 1 {
|
||||
result.addInternalError(
|
||||
new(NumberLTEError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{
|
||||
"max": resultErrorFormatNumber(*currentSubSchema.maximum),
|
||||
"max": currentSubSchema.maximum,
|
||||
},
|
||||
)
|
||||
}
|
||||
@ -801,29 +889,42 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{
|
||||
//minimum & exclusiveMinimum:
|
||||
if currentSubSchema.minimum != nil {
|
||||
if currentSubSchema.exclusiveMinimum {
|
||||
if float64Value <= *currentSubSchema.minimum {
|
||||
result.addError(
|
||||
if float64Value.Cmp(currentSubSchema.minimum) <= 0 {
|
||||
// if float64Value <= *currentSubSchema.minimum {
|
||||
result.addInternalError(
|
||||
new(NumberGTError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{
|
||||
"min": resultErrorFormatNumber(*currentSubSchema.minimum),
|
||||
"min": currentSubSchema.minimum,
|
||||
},
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if float64Value < *currentSubSchema.minimum {
|
||||
result.addError(
|
||||
if float64Value.Cmp(currentSubSchema.minimum) == -1 {
|
||||
result.addInternalError(
|
||||
new(NumberGTEError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{
|
||||
"min": resultErrorFormatNumber(*currentSubSchema.minimum),
|
||||
"min": currentSubSchema.minimum,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// format
|
||||
if currentSubSchema.format != "" {
|
||||
if !FormatCheckers.IsFormat(currentSubSchema.format, float64Value) {
|
||||
result.addInternalError(
|
||||
new(DoesNotMatchFormatError),
|
||||
context,
|
||||
value,
|
||||
ErrorDetails{"format": currentSubSchema.format},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
result.incrementScore()
|
||||
}
|
||||
|
Reference in New Issue
Block a user