chore: update docker and k8s
This commit is contained in:
parent
2b5c7f9e91
commit
c2d440a914
1283 changed files with 67741 additions and 27918 deletions
118
vendor/github.com/xeipuuv/gojsonschema/draft.go
generated
vendored
Normal file
118
vendor/github.com/xeipuuv/gojsonschema/draft.go
generated
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
// Copyright 2018 johandorland ( https://github.com/johandorland )
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gojsonschema
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/xeipuuv/gojsonreference"
|
||||
)
|
||||
|
||||
type Draft int
|
||||
|
||||
const (
|
||||
Draft4 Draft = 4
|
||||
Draft6 Draft = 6
|
||||
Draft7 Draft = 7
|
||||
Hybrid Draft = math.MaxInt32
|
||||
)
|
||||
|
||||
type draftConfig struct {
|
||||
Version Draft
|
||||
MetaSchemaURL string
|
||||
MetaSchema string
|
||||
}
|
||||
type draftConfigs []draftConfig
|
||||
|
||||
var drafts draftConfigs
|
||||
|
||||
func init() {
|
||||
drafts = []draftConfig{
|
||||
draftConfig{
|
||||
Version: Draft4,
|
||||
MetaSchemaURL: "http://json-schema.org/draft-04/schema",
|
||||
MetaSchema: `{"id":"http://json-schema.org/draft-04/schema#","$schema":"http://json-schema.org/draft-04/schema#","description":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"positiveInteger":{"type":"integer","minimum":0},"positiveIntegerDefault0":{"allOf":[{"$ref":"#/definitions/positiveInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"minItems":1,"uniqueItems":true}},"type":"object","properties":{"id":{"type":"string"},"$schema":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"multipleOf":{"type":"number","minimum":0,"exclusiveMinimum":true},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"boolean","default":false},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"boolean","default":false},"maxLength":{"$ref":"#/definitions/positiveInteger"},"minLength":{"$ref":"#/definitions/positiveIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/positiveInteger"},"minItems":{"$ref":"#/definitions/positiveIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"maxProperties":{"$ref":"#/definitions/positiveInteger"},"minProperties":{"$ref":"#/definitions/positiveIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"anyOf":[{"type":"boolean"},{"$ref":"#"}],"default":{}},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"dependencies":{"exclusiveMaximum":["maximum"],"exclusiveMinimum":["minimum"]},"default":{}}`,
|
||||
},
|
||||
draftConfig{
|
||||
Version: Draft6,
|
||||
MetaSchemaURL: "http://json-schema.org/draft-06/schema",
|
||||
MetaSchema: `{"$schema":"http://json-schema.org/draft-06/schema#","$id":"http://json-schema.org/draft-06/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"title":{"type":"string"},"description":{"type":"string"},"default":{},"examples":{"type":"array","items":{}},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":{}},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":{},"enum":{"type":"array","minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":{}}`,
|
||||
},
|
||||
draftConfig{
|
||||
Version: Draft7,
|
||||
MetaSchemaURL: "http://json-schema.org/draft-07/schema",
|
||||
MetaSchema: `{"$schema":"http://json-schema.org/draft-07/schema#","$id":"http://json-schema.org/draft-07/schema#","title":"Core schema meta-schema","definitions":{"schemaArray":{"type":"array","minItems":1,"items":{"$ref":"#"}},"nonNegativeInteger":{"type":"integer","minimum":0},"nonNegativeIntegerDefault0":{"allOf":[{"$ref":"#/definitions/nonNegativeInteger"},{"default":0}]},"simpleTypes":{"enum":["array","boolean","integer","null","number","object","string"]},"stringArray":{"type":"array","items":{"type":"string"},"uniqueItems":true,"default":[]}},"type":["object","boolean"],"properties":{"$id":{"type":"string","format":"uri-reference"},"$schema":{"type":"string","format":"uri"},"$ref":{"type":"string","format":"uri-reference"},"$comment":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"default":true,"readOnly":{"type":"boolean","default":false},"examples":{"type":"array","items":true},"multipleOf":{"type":"number","exclusiveMinimum":0},"maximum":{"type":"number"},"exclusiveMaximum":{"type":"number"},"minimum":{"type":"number"},"exclusiveMinimum":{"type":"number"},"maxLength":{"$ref":"#/definitions/nonNegativeInteger"},"minLength":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"pattern":{"type":"string","format":"regex"},"additionalItems":{"$ref":"#"},"items":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/schemaArray"}],"default":true},"maxItems":{"$ref":"#/definitions/nonNegativeInteger"},"minItems":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"uniqueItems":{"type":"boolean","default":false},"contains":{"$ref":"#"},"maxProperties":{"$ref":"#/definitions/nonNegativeInteger"},"minProperties":{"$ref":"#/definitions/nonNegativeIntegerDefault0"},"required":{"$ref":"#/definitions/stringArray"},"additionalProperties":{"$ref":"#"},"definitions":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"properties":{"type":"object","additionalProperties":{"$ref":"#"},"default":{}},"patternProperties":{"type":"object","additionalProperties":{"$ref":"#"},"propertyNames":{"format":"regex"},"default":{}},"dependencies":{"type":"object","additionalProperties":{"anyOf":[{"$ref":"#"},{"$ref":"#/definitions/stringArray"}]}},"propertyNames":{"$ref":"#"},"const":true,"enum":{"type":"array","items":true,"minItems":1,"uniqueItems":true},"type":{"anyOf":[{"$ref":"#/definitions/simpleTypes"},{"type":"array","items":{"$ref":"#/definitions/simpleTypes"},"minItems":1,"uniqueItems":true}]},"format":{"type":"string"},"contentMediaType":{"type":"string"},"contentEncoding":{"type":"string"},"if":{"$ref":"#"},"then":{"$ref":"#"},"else":{"$ref":"#"},"allOf":{"$ref":"#/definitions/schemaArray"},"anyOf":{"$ref":"#/definitions/schemaArray"},"oneOf":{"$ref":"#/definitions/schemaArray"},"not":{"$ref":"#"}},"default":true}`,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (dc draftConfigs) GetMetaSchema(url string) string {
|
||||
for _, config := range dc {
|
||||
if config.MetaSchemaURL == url {
|
||||
return config.MetaSchema
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func (dc draftConfigs) GetDraftVersion(url string) *Draft {
|
||||
for _, config := range dc {
|
||||
if config.MetaSchemaURL == url {
|
||||
return &config.Version
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (dc draftConfigs) GetSchemaURL(draft Draft) string {
|
||||
for _, config := range dc {
|
||||
if config.Version == draft {
|
||||
return config.MetaSchemaURL
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func parseSchemaURL(documentNode interface{}) (string, *Draft, error) {
|
||||
|
||||
if isKind(documentNode, reflect.Bool) {
|
||||
return "", nil, nil
|
||||
}
|
||||
m := documentNode.(map[string]interface{})
|
||||
|
||||
if existsMapKey(m, KEY_SCHEMA) {
|
||||
if !isKind(m[KEY_SCHEMA], reflect.String) {
|
||||
return "", nil, errors.New(formatErrorDescription(
|
||||
Locale.MustBeOfType(),
|
||||
ErrorDetails{
|
||||
"key": KEY_SCHEMA,
|
||||
"type": TYPE_STRING,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
schemaReference, err := gojsonreference.NewJsonReference(m[KEY_SCHEMA].(string))
|
||||
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
schema := schemaReference.String()
|
||||
|
||||
return schema, drafts.GetDraftVersion(schema), nil
|
||||
}
|
||||
|
||||
return "", nil, nil
|
||||
}
|
47
vendor/github.com/xeipuuv/gojsonschema/errors.go
generated
vendored
47
vendor/github.com/xeipuuv/gojsonschema/errors.go
generated
vendored
|
@ -56,6 +56,11 @@ type (
|
|||
ResultErrorFields
|
||||
}
|
||||
|
||||
// ConstError. ErrorDetails: allowed
|
||||
ConstError struct {
|
||||
ResultErrorFields
|
||||
}
|
||||
|
||||
// EnumError. ErrorDetails: allowed
|
||||
EnumError struct {
|
||||
ResultErrorFields
|
||||
|
@ -76,11 +81,16 @@ type (
|
|||
ResultErrorFields
|
||||
}
|
||||
|
||||
// ItemsMustBeUniqueError. ErrorDetails: type
|
||||
// ItemsMustBeUniqueError. ErrorDetails: type, i, j
|
||||
ItemsMustBeUniqueError struct {
|
||||
ResultErrorFields
|
||||
}
|
||||
|
||||
// ArrayContainsError. ErrorDetails:
|
||||
ArrayContainsError struct {
|
||||
ResultErrorFields
|
||||
}
|
||||
|
||||
// ArrayMinPropertiesError. ErrorDetails: min
|
||||
ArrayMinPropertiesError struct {
|
||||
ResultErrorFields
|
||||
|
@ -101,6 +111,11 @@ type (
|
|||
ResultErrorFields
|
||||
}
|
||||
|
||||
// InvalidPopertyNameError. ErrorDetails: property
|
||||
InvalidPropertyNameError struct {
|
||||
ResultErrorFields
|
||||
}
|
||||
|
||||
// StringLengthGTEError. ErrorDetails: min
|
||||
StringLengthGTEError struct {
|
||||
ResultErrorFields
|
||||
|
@ -145,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) {
|
||||
|
@ -176,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()
|
||||
|
@ -191,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()
|
||||
|
@ -203,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()
|
||||
|
@ -230,19 +264,26 @@ 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()
|
||||
|
||||
if _, exists := details["context"]; !exists && context != nil {
|
||||
details["context"] = context.String()
|
||||
}
|
||||
|
||||
err.SetDescription(formatErrorDescription(d, details))
|
||||
err.SetDescription(formatErrorDescription(err.DescriptionFormat(), details))
|
||||
}
|
||||
|
||||
// formatErrorDescription takes a string in the default text/template
|
||||
|
|
224
vendor/github.com/xeipuuv/gojsonschema/format_checkers.go
generated
vendored
224
vendor/github.com/xeipuuv/gojsonschema/format_checkers.go
generated
vendored
|
@ -2,17 +2,18 @@ package gojsonschema
|
|||
|
||||
import (
|
||||
"net"
|
||||
"net/mail"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
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,12 +53,19 @@ type (
|
|||
// http://tools.ietf.org/html/rfc3339#section-5.6
|
||||
DateTimeFormatChecker struct{}
|
||||
|
||||
DateFormatChecker struct{}
|
||||
|
||||
TimeFormatChecker struct{}
|
||||
|
||||
// URIFormatChecker validates a URI with a valid Scheme per RFC3986
|
||||
URIFormatChecker struct{}
|
||||
|
||||
// URIReferenceFormatChecker validates a URI or relative-reference per RFC3986
|
||||
URIReferenceFormatChecker struct{}
|
||||
|
||||
// URITemplateFormatChecker validates a URI template per RFC6570
|
||||
URITemplateFormatChecker struct{}
|
||||
|
||||
// HostnameFormatChecker validates a hostname is in the correct format
|
||||
HostnameFormatChecker struct{}
|
||||
|
||||
|
@ -66,6 +74,12 @@ type (
|
|||
|
||||
// RegexFormatChecker validates a regex is in the correct format
|
||||
RegexFormatChecker struct{}
|
||||
|
||||
// JSONPointerFormatChecker validates a JSON Pointer per RFC6901
|
||||
JSONPointerFormatChecker struct{}
|
||||
|
||||
// RelativeJSONPointerFormatChecker validates a relative JSON Pointer is in the correct format
|
||||
RelativeJSONPointerFormatChecker struct{}
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -73,45 +87,65 @@ 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{},
|
||||
"uri-reference": URIReferenceFormatChecker{},
|
||||
"uuid": UUIDFormatChecker{},
|
||||
"regex": RegexFormatChecker{},
|
||||
"date": DateFormatChecker{},
|
||||
"time": TimeFormatChecker{},
|
||||
"date-time": DateTimeFormatChecker{},
|
||||
"hostname": HostnameFormatChecker{},
|
||||
"email": EmailFormatChecker{},
|
||||
"idn-email": EmailFormatChecker{},
|
||||
"ipv4": IPV4FormatChecker{},
|
||||
"ipv6": IPV6FormatChecker{},
|
||||
"uri": URIFormatChecker{},
|
||||
"uri-reference": URIReferenceFormatChecker{},
|
||||
"iri": URIFormatChecker{},
|
||||
"iri-reference": URIReferenceFormatChecker{},
|
||||
"uri-template": URITemplateFormatChecker{},
|
||||
"uuid": UUIDFormatChecker{},
|
||||
"regex": RegexFormatChecker{},
|
||||
"json-pointer": JSONPointerFormatChecker{},
|
||||
"relative-json-pointer": RelativeJSONPointerFormatChecker{},
|
||||
},
|
||||
}
|
||||
|
||||
// Regex credit: https://github.com/asaskevich/govalidator
|
||||
rxEmail = regexp.MustCompile("^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$")
|
||||
|
||||
// Regex credit: https://www.socketloop.com/tutorials/golang-validate-hostname
|
||||
rxHostname = regexp.MustCompile(`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$`)
|
||||
|
||||
// Use a regex to make sure curly brackets are balanced properly after validating it as a AURI
|
||||
rxURITemplate = regexp.MustCompile("^([^{]*({[^}]*})?)*$")
|
||||
|
||||
rxUUID = regexp.MustCompile("^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")
|
||||
|
||||
rxJSONPointer = regexp.MustCompile("^(?:/(?:[^~/]|~0|~1)*)*$")
|
||||
|
||||
rxRelJSONPointer = regexp.MustCompile("^(?:0|[1-9][0-9]*)(?:#|(?:/(?:[^~/]|~0|~1)*)*)$")
|
||||
|
||||
lock = new(sync.Mutex)
|
||||
)
|
||||
|
||||
// Add adds a FormatChecker to the FormatCheckerChain
|
||||
// The name used will be the value used for the format key in your json schema
|
||||
func (c *FormatCheckerChain) Add(name string, f FormatChecker) *FormatCheckerChain {
|
||||
lock.Lock()
|
||||
c.formatters[name] = f
|
||||
lock.Unlock()
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// Remove deletes a FormatChecker from the FormatCheckerChain (if it exists)
|
||||
func (c *FormatCheckerChain) Remove(name string) *FormatCheckerChain {
|
||||
lock.Lock()
|
||||
delete(c.formatters, name)
|
||||
lock.Unlock()
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// Has checks to see if the FormatCheckerChain holds a FormatChecker with the given name
|
||||
func (c *FormatCheckerChain) Has(name string) bool {
|
||||
lock.Lock()
|
||||
_, ok := c.formatters[name]
|
||||
lock.Unlock()
|
||||
|
||||
return ok
|
||||
}
|
||||
|
@ -125,32 +159,52 @@ 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)
|
||||
_, err := mail.ParseAddress(asString)
|
||||
|
||||
return f.IsFormat(inputString)
|
||||
}
|
||||
|
||||
func (f EmailFormatChecker) IsFormat(input string) bool {
|
||||
return rxEmail.MatchString(input)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// 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",
|
||||
|
@ -160,7 +214,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
|
||||
}
|
||||
}
|
||||
|
@ -168,36 +222,122 @@ func (f DateTimeFormatChecker) IsFormat(input string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (f URIFormatChecker) IsFormat(input string) bool {
|
||||
u, err := url.Parse(input)
|
||||
func (f DateFormatChecker) IsFormat(input interface{}) bool {
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
_, err := time.Parse("2006-01-02", asString)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (f TimeFormatChecker) IsFormat(input interface{}) bool {
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
if _, err := time.Parse("15:04:05Z07:00", asString); err == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
_, err := time.Parse("15:04:05", asString)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
return true
|
||||
return !strings.Contains(asString, `\`)
|
||||
}
|
||||
|
||||
func (f URIReferenceFormatChecker) IsFormat(input string) bool {
|
||||
_, err := url.Parse(input)
|
||||
return err == nil
|
||||
func (f URIReferenceFormatChecker) IsFormat(input interface{}) bool {
|
||||
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
_, err := url.Parse(asString)
|
||||
return err == nil && !strings.Contains(asString, `\`)
|
||||
}
|
||||
|
||||
func (f HostnameFormatChecker) IsFormat(input string) bool {
|
||||
return rxHostname.MatchString(input) && len(input) < 256
|
||||
func (f URITemplateFormatChecker) IsFormat(input interface{}) bool {
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
u, err := url.Parse(asString)
|
||||
if err != nil || strings.Contains(asString, `\`) {
|
||||
return false
|
||||
}
|
||||
|
||||
return rxURITemplate.MatchString(u.Path)
|
||||
}
|
||||
|
||||
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 string) bool {
|
||||
if input == "" {
|
||||
func (f RegexFormatChecker) IsFormat(input interface{}) bool {
|
||||
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
if asString == "" {
|
||||
return true
|
||||
}
|
||||
_, err := regexp.Compile(input)
|
||||
_, err := regexp.Compile(asString)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (f JSONPointerFormatChecker) IsFormat(input interface{}) bool {
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
return rxJSONPointer.MatchString(asString)
|
||||
}
|
||||
|
||||
func (f RelativeJSONPointerFormatChecker) IsFormat(input interface{}) bool {
|
||||
asString, ok := input.(string)
|
||||
if ok == false {
|
||||
return false
|
||||
}
|
||||
|
||||
return rxRelJSONPointer.MatchString(asString)
|
||||
}
|
||||
|
|
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)
|
||||
|
||||
|
|
54
vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go
generated
vendored
54
vendor/github.com/xeipuuv/gojsonschema/jsonLoader.go
generated
vendored
|
@ -38,7 +38,6 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
|
||||
|
||||
"github.com/xeipuuv/gojsonreference"
|
||||
)
|
||||
|
||||
|
@ -108,7 +107,7 @@ func (l *jsonReferenceLoader) LoaderFactory() JSONLoaderFactory {
|
|||
}
|
||||
|
||||
// NewReferenceLoader returns a JSON reference loader using the given source and the local OS file system.
|
||||
func NewReferenceLoader(source string) *jsonReferenceLoader {
|
||||
func NewReferenceLoader(source string) JSONLoader {
|
||||
return &jsonReferenceLoader{
|
||||
fs: osFS,
|
||||
source: source,
|
||||
|
@ -116,7 +115,7 @@ func NewReferenceLoader(source string) *jsonReferenceLoader {
|
|||
}
|
||||
|
||||
// NewReferenceLoaderFileSystem returns a JSON reference loader using the given source and file system.
|
||||
func NewReferenceLoaderFileSystem(source string, fs http.FileSystem) *jsonReferenceLoader {
|
||||
func NewReferenceLoaderFileSystem(source string, fs http.FileSystem) JSONLoader {
|
||||
return &jsonReferenceLoader{
|
||||
fs: fs,
|
||||
source: source,
|
||||
|
@ -139,13 +138,11 @@ func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) {
|
|||
|
||||
if reference.HasFileScheme {
|
||||
|
||||
filename := strings.Replace(refToUrl.GetUrl().Path, "file://", "", -1)
|
||||
filename := strings.TrimPrefix(refToUrl.String(), "file://")
|
||||
if runtime.GOOS == "windows" {
|
||||
// on Windows, a file URL may have an extra leading slash, use slashes
|
||||
// instead of backslashes, and have spaces escaped
|
||||
if strings.HasPrefix(filename, "/") {
|
||||
filename = filename[1:]
|
||||
}
|
||||
filename = strings.TrimPrefix(filename, "/")
|
||||
filename = filepath.FromSlash(filename)
|
||||
}
|
||||
|
||||
|
@ -169,6 +166,12 @@ func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) {
|
|||
|
||||
func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error) {
|
||||
|
||||
// returned cached versions for metaschemas for drafts 4, 6 and 7
|
||||
// for performance and allow for easier offline use
|
||||
if metaSchema := drafts.GetMetaSchema(address); metaSchema != "" {
|
||||
return decodeJsonUsingNumber(strings.NewReader(metaSchema))
|
||||
}
|
||||
|
||||
resp, err := http.Get(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -185,7 +188,6 @@ func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error)
|
|||
}
|
||||
|
||||
return decodeJsonUsingNumber(bytes.NewReader(bodyBuff))
|
||||
|
||||
}
|
||||
|
||||
func (l *jsonReferenceLoader) loadFromFile(path string) (interface{}, error) {
|
||||
|
@ -222,7 +224,7 @@ func (l *jsonStringLoader) LoaderFactory() JSONLoaderFactory {
|
|||
return &DefaultJSONLoaderFactory{}
|
||||
}
|
||||
|
||||
func NewStringLoader(source string) *jsonStringLoader {
|
||||
func NewStringLoader(source string) JSONLoader {
|
||||
return &jsonStringLoader{source: source}
|
||||
}
|
||||
|
||||
|
@ -250,7 +252,7 @@ func (l *jsonBytesLoader) LoaderFactory() JSONLoaderFactory {
|
|||
return &DefaultJSONLoaderFactory{}
|
||||
}
|
||||
|
||||
func NewBytesLoader(source []byte) *jsonBytesLoader {
|
||||
func NewBytesLoader(source []byte) JSONLoader {
|
||||
return &jsonBytesLoader{source: source}
|
||||
}
|
||||
|
||||
|
@ -277,7 +279,7 @@ func (l *jsonGoLoader) LoaderFactory() JSONLoaderFactory {
|
|||
return &DefaultJSONLoaderFactory{}
|
||||
}
|
||||
|
||||
func NewGoLoader(source interface{}) *jsonGoLoader {
|
||||
func NewGoLoader(source interface{}) JSONLoader {
|
||||
return &jsonGoLoader{source: source}
|
||||
}
|
||||
|
||||
|
@ -298,12 +300,12 @@ type jsonIOLoader struct {
|
|||
buf *bytes.Buffer
|
||||
}
|
||||
|
||||
func NewReaderLoader(source io.Reader) (*jsonIOLoader, io.Reader) {
|
||||
func NewReaderLoader(source io.Reader) (JSONLoader, io.Reader) {
|
||||
buf := &bytes.Buffer{}
|
||||
return &jsonIOLoader{buf: buf}, io.TeeReader(source, buf)
|
||||
}
|
||||
|
||||
func NewWriterLoader(source io.Writer) (*jsonIOLoader, io.Writer) {
|
||||
func NewWriterLoader(source io.Writer) (JSONLoader, io.Writer) {
|
||||
buf := &bytes.Buffer{}
|
||||
return &jsonIOLoader{buf: buf}, io.MultiWriter(source, buf)
|
||||
}
|
||||
|
@ -324,6 +326,30 @@ 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) {
|
||||
|
||||
var document interface{}
|
||||
|
@ -335,7 +361,7 @@ func decodeJsonUsingNumber(r io.Reader) (interface{}, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
return document, nil
|
||||
|
||||
}
|
||||
|
|
19
vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/LICENSE
generated
vendored
19
vendor/github.com/xeipuuv/gojsonschema/json_schema_test_suite/LICENSE
generated
vendored
|
@ -1,19 +0,0 @@
|
|||
Copyright (c) 2012 Julian Berman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
33
vendor/github.com/xeipuuv/gojsonschema/locales.go
generated
vendored
33
vendor/github.com/xeipuuv/gojsonschema/locales.go
generated
vendored
|
@ -36,16 +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
|
||||
|
@ -76,6 +79,9 @@ type (
|
|||
HttpBadStatus() string
|
||||
ParseError() string
|
||||
|
||||
ConditionThen() string
|
||||
ConditionElse() string
|
||||
|
||||
// ErrorFormat
|
||||
ErrorFormat() string
|
||||
}
|
||||
|
@ -116,6 +122,10 @@ func (l DefaultLocale) Internal() string {
|
|||
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}}`
|
||||
}
|
||||
|
@ -137,7 +147,11 @@ func (l DefaultLocale) ArrayMaxItems() string {
|
|||
}
|
||||
|
||||
func (l DefaultLocale) Unique() string {
|
||||
return `{{.type}} items must be unique`
|
||||
return `{{.type}} items[{{.i}},{{.j}}] must be unique`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) ArrayContains() string {
|
||||
return `At least one of the items must match`
|
||||
}
|
||||
|
||||
func (l DefaultLocale) ArrayMinProperties() string {
|
||||
|
@ -156,6 +170,10 @@ func (l DefaultLocale) InvalidPropertyPattern() string {
|
|||
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}}`
|
||||
}
|
||||
|
@ -268,14 +286,23 @@ func (l DefaultLocale) ErrorFormat() string {
|
|||
|
||||
//Parse error
|
||||
func (l DefaultLocale) ParseError() string {
|
||||
return `Expected: %expected%, given: Invalid JSON`
|
||||
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"
|
||||
|
|
49
vendor/github.com/xeipuuv/gojsonschema/result.go
generated
vendored
49
vendor/github.com/xeipuuv/gojsonschema/result.go
generated
vendored
|
@ -40,10 +40,12 @@ 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)
|
||||
|
@ -55,11 +57,12 @@ type (
|
|||
// 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 {
|
||||
|
@ -73,12 +76,6 @@ type (
|
|||
// Field outputs the field name without the root context
|
||||
// i.e. firstName or person.firstName instead of (root).firstName or (root).person.firstName
|
||||
func (v *ResultErrorFields) Field() string {
|
||||
if p, ok := v.Details()["property"]; ok {
|
||||
if str, isString := p.(string); isString {
|
||||
return str
|
||||
}
|
||||
}
|
||||
|
||||
return strings.TrimPrefix(v.context.String(), STRING_ROOT_SCHEMA_PROPERTY+".")
|
||||
}
|
||||
|
||||
|
@ -90,11 +87,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
|
||||
}
|
||||
|
||||
|
@ -106,6 +103,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
|
||||
}
|
||||
|
@ -155,7 +160,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
|
||||
|
|
457
vendor/github.com/xeipuuv/gojsonschema/schema.go
generated
vendored
457
vendor/github.com/xeipuuv/gojsonschema/schema.go
generated
vendored
|
@ -27,8 +27,8 @@
|
|||
package gojsonschema
|
||||
|
||||
import (
|
||||
// "encoding/json"
|
||||
"errors"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"text/template"
|
||||
|
@ -46,39 +46,7 @@ var (
|
|||
)
|
||||
|
||||
func NewSchema(l JSONLoader) (*Schema, error) {
|
||||
ref, err := l.JsonReference()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := Schema{}
|
||||
d.pool = newSchemaPool(l.LoaderFactory())
|
||||
d.documentReference = ref
|
||||
d.referencePool = newSchemaReferencePool()
|
||||
|
||||
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.SetStandaloneDocument(doc)
|
||||
}
|
||||
|
||||
err = d.parse(doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &d, nil
|
||||
return NewSchemaLoader().Compile(l)
|
||||
}
|
||||
|
||||
type Schema struct {
|
||||
|
@ -88,8 +56,8 @@ type Schema struct {
|
|||
referencePool *schemaReferencePool
|
||||
}
|
||||
|
||||
func (d *Schema) parse(document interface{}) error {
|
||||
d.rootSchema = &subSchema{property: STRING_ROOT_SCHEMA_PROPERTY}
|
||||
func (d *Schema) parse(document interface{}, draft Draft) error {
|
||||
d.rootSchema = &subSchema{property: STRING_ROOT_SCHEMA_PROPERTY, draft: &draft}
|
||||
return d.parseSchema(document, d.rootSchema)
|
||||
}
|
||||
|
||||
|
@ -105,6 +73,23 @@ func (d *Schema) SetRootSchemaName(name string) {
|
|||
//
|
||||
func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema) error {
|
||||
|
||||
if currentSchema.draft == nil {
|
||||
if currentSchema.parent == nil {
|
||||
return errors.New("Draft not set")
|
||||
}
|
||||
currentSchema.draft = currentSchema.parent.draft
|
||||
}
|
||||
|
||||
// As of draft 6 "true" is equivalent to an empty schema "{}" and false equals "{"not":{}}"
|
||||
if *currentSchema.draft >= Draft6 && 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.ParseError(),
|
||||
|
@ -116,81 +101,67 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
|||
|
||||
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 currentSchema.id == nil && currentSchema.parent != nil {
|
||||
currentSchema.id = currentSchema.parent.id
|
||||
}
|
||||
|
||||
// $ref
|
||||
if existsMapKey(m, KEY_REF) && !isKind(m[KEY_REF], reflect.String) {
|
||||
// In draft 6 the id keyword was renamed to $id
|
||||
// Hybrid mode uses the old id by default
|
||||
var keyID string
|
||||
|
||||
switch *currentSchema.draft {
|
||||
case Draft4:
|
||||
keyID = KEY_ID
|
||||
case Hybrid:
|
||||
keyID = KEY_ID_NEW
|
||||
if existsMapKey(m, KEY_ID) {
|
||||
keyID = KEY_ID
|
||||
}
|
||||
default:
|
||||
keyID = KEY_ID_NEW
|
||||
}
|
||||
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 k, ok := m[keyID].(string); ok {
|
||||
jsonReference, err := gojsonreference.NewJsonReference(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if jsonReference.HasFullUrl {
|
||||
currentSchema.ref = &jsonReference
|
||||
if currentSchema == d.rootSchema {
|
||||
currentSchema.id = &jsonReference
|
||||
} else {
|
||||
inheritedReference, err := currentSchema.ref.Inherits(jsonReference)
|
||||
ref, err := currentSchema.parent.id.Inherits(jsonReference)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
currentSchema.ref = inheritedReference
|
||||
}
|
||||
|
||||
if sch, ok := d.referencePool.Get(currentSchema.ref.String() + k); ok {
|
||||
currentSchema.refSchema = sch
|
||||
|
||||
} else {
|
||||
err := d.parseReference(documentNode, currentSchema, k)
|
||||
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(
|
||||
|
@ -214,20 +185,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(
|
||||
|
@ -256,6 +213,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) {
|
||||
|
@ -357,6 +347,26 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
|||
}
|
||||
}
|
||||
|
||||
// propertyNames
|
||||
if existsMapKey(m, KEY_PROPERTY_NAMES) && *currentSchema.draft >= Draft6 {
|
||||
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)
|
||||
|
@ -369,7 +379,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)
|
||||
|
@ -388,7 +398,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)
|
||||
|
@ -443,7 +453,7 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
|||
},
|
||||
))
|
||||
}
|
||||
if *multipleOfValue <= 0 {
|
||||
if multipleOfValue.Cmp(big.NewRat(0, 1)) <= 0 {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.GreaterThanZero(),
|
||||
ErrorDetails{"number": KEY_MULTIPLE_OF},
|
||||
|
@ -464,20 +474,62 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
|||
}
|
||||
|
||||
if existsMapKey(m, KEY_EXCLUSIVE_MINIMUM) {
|
||||
if isKind(m[KEY_EXCLUSIVE_MINIMUM], reflect.Bool) {
|
||||
switch *currentSchema.draft {
|
||||
case Draft4:
|
||||
if !isKind(m[KEY_EXCLUSIVE_MINIMUM], reflect.Bool) {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{
|
||||
"expected": TYPE_BOOLEAN,
|
||||
"given": KEY_EXCLUSIVE_MINIMUM,
|
||||
},
|
||||
))
|
||||
}
|
||||
if currentSchema.minimum == nil {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.CannotBeUsedWithout(),
|
||||
ErrorDetails{"x": KEY_EXCLUSIVE_MINIMUM, "y": KEY_MINIMUM},
|
||||
))
|
||||
}
|
||||
exclusiveMinimumValue := m[KEY_EXCLUSIVE_MINIMUM].(bool)
|
||||
currentSchema.exclusiveMinimum = exclusiveMinimumValue
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.MustBeOfA(),
|
||||
ErrorDetails{"x": KEY_EXCLUSIVE_MINIMUM, "y": TYPE_BOOLEAN},
|
||||
))
|
||||
if m[KEY_EXCLUSIVE_MINIMUM].(bool) {
|
||||
currentSchema.exclusiveMinimum = currentSchema.minimum
|
||||
currentSchema.minimum = nil
|
||||
}
|
||||
case Hybrid:
|
||||
if isKind(m[KEY_EXCLUSIVE_MINIMUM], reflect.Bool) {
|
||||
if currentSchema.minimum == nil {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.CannotBeUsedWithout(),
|
||||
ErrorDetails{"x": KEY_EXCLUSIVE_MINIMUM, "y": KEY_MINIMUM},
|
||||
))
|
||||
}
|
||||
if m[KEY_EXCLUSIVE_MINIMUM].(bool) {
|
||||
currentSchema.exclusiveMinimum = currentSchema.minimum
|
||||
currentSchema.minimum = nil
|
||||
}
|
||||
} else if isJsonNumber(m[KEY_EXCLUSIVE_MINIMUM]) {
|
||||
currentSchema.exclusiveMinimum = mustBeNumber(m[KEY_EXCLUSIVE_MINIMUM])
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{
|
||||
"expected": TYPE_BOOLEAN + "/" + TYPE_NUMBER,
|
||||
"given": KEY_EXCLUSIVE_MINIMUM,
|
||||
},
|
||||
))
|
||||
}
|
||||
default:
|
||||
if isJsonNumber(m[KEY_EXCLUSIVE_MINIMUM]) {
|
||||
currentSchema.exclusiveMinimum = mustBeNumber(m[KEY_EXCLUSIVE_MINIMUM])
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{
|
||||
"expected": TYPE_NUMBER,
|
||||
"given": KEY_EXCLUSIVE_MINIMUM,
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -493,29 +545,62 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
|||
}
|
||||
|
||||
if existsMapKey(m, KEY_EXCLUSIVE_MAXIMUM) {
|
||||
if isKind(m[KEY_EXCLUSIVE_MAXIMUM], reflect.Bool) {
|
||||
switch *currentSchema.draft {
|
||||
case Draft4:
|
||||
if !isKind(m[KEY_EXCLUSIVE_MAXIMUM], reflect.Bool) {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{
|
||||
"expected": TYPE_BOOLEAN,
|
||||
"given": KEY_EXCLUSIVE_MAXIMUM,
|
||||
},
|
||||
))
|
||||
}
|
||||
if currentSchema.maximum == nil {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.CannotBeUsedWithout(),
|
||||
ErrorDetails{"x": KEY_EXCLUSIVE_MAXIMUM, "y": KEY_MAXIMUM},
|
||||
))
|
||||
}
|
||||
exclusiveMaximumValue := m[KEY_EXCLUSIVE_MAXIMUM].(bool)
|
||||
currentSchema.exclusiveMaximum = exclusiveMaximumValue
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.MustBeOfA(),
|
||||
ErrorDetails{"x": KEY_EXCLUSIVE_MAXIMUM, "y": STRING_NUMBER},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
if currentSchema.minimum != nil && currentSchema.maximum != nil {
|
||||
if *currentSchema.minimum > *currentSchema.maximum {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.CannotBeGT(),
|
||||
ErrorDetails{"x": KEY_MINIMUM, "y": KEY_MAXIMUM},
|
||||
))
|
||||
if m[KEY_EXCLUSIVE_MAXIMUM].(bool) {
|
||||
currentSchema.exclusiveMaximum = currentSchema.maximum
|
||||
currentSchema.maximum = nil
|
||||
}
|
||||
case Hybrid:
|
||||
if isKind(m[KEY_EXCLUSIVE_MAXIMUM], reflect.Bool) {
|
||||
if currentSchema.maximum == nil {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.CannotBeUsedWithout(),
|
||||
ErrorDetails{"x": KEY_EXCLUSIVE_MAXIMUM, "y": KEY_MAXIMUM},
|
||||
))
|
||||
}
|
||||
if m[KEY_EXCLUSIVE_MAXIMUM].(bool) {
|
||||
currentSchema.exclusiveMaximum = currentSchema.maximum
|
||||
currentSchema.maximum = nil
|
||||
}
|
||||
} else if isJsonNumber(m[KEY_EXCLUSIVE_MAXIMUM]) {
|
||||
currentSchema.exclusiveMaximum = mustBeNumber(m[KEY_EXCLUSIVE_MAXIMUM])
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{
|
||||
"expected": TYPE_BOOLEAN + "/" + TYPE_NUMBER,
|
||||
"given": KEY_EXCLUSIVE_MAXIMUM,
|
||||
},
|
||||
))
|
||||
}
|
||||
default:
|
||||
if isJsonNumber(m[KEY_EXCLUSIVE_MAXIMUM]) {
|
||||
currentSchema.exclusiveMaximum = mustBeNumber(m[KEY_EXCLUSIVE_MAXIMUM])
|
||||
} else {
|
||||
return errors.New(formatErrorDescription(
|
||||
Locale.InvalidType(),
|
||||
ErrorDetails{
|
||||
"expected": TYPE_NUMBER,
|
||||
"given": KEY_EXCLUSIVE_MAXIMUM,
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -586,11 +671,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]},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -710,8 +790,24 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
|||
}
|
||||
}
|
||||
|
||||
if existsMapKey(m, KEY_CONTAINS) && *currentSchema.draft >= Draft6 {
|
||||
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) && *currentSchema.draft >= Draft6 {
|
||||
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{}) {
|
||||
|
@ -785,7 +881,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)
|
||||
|
@ -800,48 +896,91 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
|
|||
}
|
||||
}
|
||||
|
||||
if *currentSchema.draft >= Draft7 {
|
||||
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) error {
|
||||
var refdDocumentNode interface{}
|
||||
jsonPointer := currentSchema.ref.GetPointer()
|
||||
standaloneDocument := d.pool.GetStandaloneDocument()
|
||||
func (d *Schema) parseReference(documentNode interface{}, currentSchema *subSchema) error {
|
||||
var (
|
||||
refdDocumentNode interface{}
|
||||
dsp *schemaPoolDocument
|
||||
err error
|
||||
)
|
||||
|
||||
if standaloneDocument != nil {
|
||||
newSchema := &subSchema{property: KEY_REF, parent: currentSchema, ref: currentSchema.ref}
|
||||
|
||||
var err error
|
||||
refdDocumentNode, _, err = jsonPointer.Get(standaloneDocument)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.referencePool.Add(currentSchema.ref.String(), newSchema)
|
||||
|
||||
} else {
|
||||
dsp, err := d.pool.GetDocument(*currentSchema.ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dsp, err = d.pool.GetDocument(*currentSchema.ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newSchema.id = currentSchema.ref
|
||||
|
||||
refdDocumentNode, _, err = jsonPointer.Get(dsp.Document)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
refdDocumentNode = dsp.Document
|
||||
newSchema.draft = dsp.Draft
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -909,7 +1048,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 {
|
||||
|
|
203
vendor/github.com/xeipuuv/gojsonschema/schemaLoader.go
generated
vendored
Normal file
203
vendor/github.com/xeipuuv/gojsonschema/schemaLoader.go
generated
vendored
Normal file
|
@ -0,0 +1,203 @@
|
|||
// Copyright 2018 johandorland ( https://github.com/johandorland )
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gojsonschema
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
|
||||
"github.com/xeipuuv/gojsonreference"
|
||||
)
|
||||
|
||||
type SchemaLoader struct {
|
||||
pool *schemaPool
|
||||
AutoDetect bool
|
||||
Validate bool
|
||||
Draft Draft
|
||||
}
|
||||
|
||||
func NewSchemaLoader() *SchemaLoader {
|
||||
|
||||
ps := &SchemaLoader{
|
||||
pool: &schemaPool{
|
||||
schemaPoolDocuments: make(map[string]*schemaPoolDocument),
|
||||
},
|
||||
AutoDetect: true,
|
||||
Validate: false,
|
||||
Draft: Hybrid,
|
||||
}
|
||||
ps.pool.autoDetect = &ps.AutoDetect
|
||||
|
||||
return ps
|
||||
}
|
||||
|
||||
func (sl *SchemaLoader) validateMetaschema(documentNode interface{}) error {
|
||||
|
||||
var (
|
||||
schema string
|
||||
err error
|
||||
)
|
||||
if sl.AutoDetect {
|
||||
schema, _, err = parseSchemaURL(documentNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// If no explicit "$schema" is used, use the default metaschema associated with the draft used
|
||||
if schema == "" {
|
||||
if sl.Draft == Hybrid {
|
||||
return nil
|
||||
}
|
||||
schema = drafts.GetSchemaURL(sl.Draft)
|
||||
}
|
||||
|
||||
//Disable validation when loading the metaschema to prevent an infinite recursive loop
|
||||
sl.Validate = false
|
||||
|
||||
metaSchema, err := sl.Compile(NewReferenceLoader(schema))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sl.Validate = true
|
||||
|
||||
result := metaSchema.validateDocument(documentNode)
|
||||
|
||||
if !result.Valid() {
|
||||
var res bytes.Buffer
|
||||
for _, err := range result.Errors() {
|
||||
res.WriteString(err.String())
|
||||
res.WriteString("\n")
|
||||
}
|
||||
return errors.New(res.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddSchemas adds an arbritrary amount of schemas to the schema cache. As this function does not require
|
||||
// an explicit URL, every schema should contain an $id, so that it can be referenced by the main schema
|
||||
func (sl *SchemaLoader) AddSchemas(loaders ...JSONLoader) error {
|
||||
emptyRef, _ := gojsonreference.NewJsonReference("")
|
||||
|
||||
for _, loader := range loaders {
|
||||
doc, err := loader.LoadJSON()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if sl.Validate {
|
||||
if err := sl.validateMetaschema(doc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Directly use the Recursive function, so that it get only added to the schema pool by $id
|
||||
// and not by the ref of the document as it's empty
|
||||
if err = sl.pool.parseReferences(doc, emptyRef, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//AddSchema adds a schema under the provided URL to the schema cache
|
||||
func (sl *SchemaLoader) AddSchema(url string, loader JSONLoader) error {
|
||||
|
||||
ref, err := gojsonreference.NewJsonReference(url)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
doc, err := loader.LoadJSON()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if sl.Validate {
|
||||
if err := sl.validateMetaschema(doc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return sl.pool.parseReferences(doc, ref, true)
|
||||
}
|
||||
|
||||
func (sl *SchemaLoader) Compile(rootSchema JSONLoader) (*Schema, error) {
|
||||
|
||||
ref, err := rootSchema.JsonReference()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := Schema{}
|
||||
d.pool = sl.pool
|
||||
d.pool.jsonLoaderFactory = rootSchema.LoaderFactory()
|
||||
d.documentReference = ref
|
||||
d.referencePool = newSchemaReferencePool()
|
||||
|
||||
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 = rootSchema.LoadJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// References need only be parsed if loading JSON directly
|
||||
// as pool.GetDocument already does this for us if loading by reference
|
||||
err = sl.pool.parseReferences(doc, ref, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if sl.Validate {
|
||||
if err := sl.validateMetaschema(doc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
draft := sl.Draft
|
||||
if sl.AutoDetect {
|
||||
_, detectedDraft, err := parseSchemaURL(doc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if detectedDraft != nil {
|
||||
draft = *detectedDraft
|
||||
}
|
||||
}
|
||||
|
||||
err = d.parse(doc, draft)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &d, nil
|
||||
}
|
180
vendor/github.com/xeipuuv/gojsonschema/schemaPool.go
generated
vendored
180
vendor/github.com/xeipuuv/gojsonschema/schemaPool.go
generated
vendored
|
@ -28,82 +28,188 @@ package gojsonschema
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/xeipuuv/gojsonreference"
|
||||
)
|
||||
|
||||
type schemaPoolDocument struct {
|
||||
Document interface{}
|
||||
Draft *Draft
|
||||
}
|
||||
|
||||
type schemaPool struct {
|
||||
schemaPoolDocuments map[string]*schemaPoolDocument
|
||||
standaloneDocument interface{}
|
||||
jsonLoaderFactory JSONLoaderFactory
|
||||
autoDetect *bool
|
||||
}
|
||||
|
||||
func newSchemaPool(f JSONLoaderFactory) *schemaPool {
|
||||
func (p *schemaPool) parseReferences(document interface{}, ref gojsonreference.JsonReference, pooled bool) error {
|
||||
|
||||
p := &schemaPool{}
|
||||
p.schemaPoolDocuments = make(map[string]*schemaPoolDocument)
|
||||
p.standaloneDocument = nil
|
||||
p.jsonLoaderFactory = f
|
||||
var (
|
||||
draft *Draft
|
||||
err error
|
||||
reference = ref.String()
|
||||
)
|
||||
// Only the root document should be added to the schema pool if pooled is true
|
||||
if _, ok := p.schemaPoolDocuments[reference]; pooled && ok {
|
||||
return fmt.Errorf("Reference already exists: \"%s\"", reference)
|
||||
}
|
||||
|
||||
return p
|
||||
if *p.autoDetect {
|
||||
_, draft, err = parseSchemaURL(document)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = p.parseReferencesRecursive(document, ref, draft)
|
||||
|
||||
if pooled {
|
||||
p.schemaPoolDocuments[reference] = &schemaPoolDocument{Document: document, Draft: draft}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *schemaPool) SetStandaloneDocument(document interface{}) {
|
||||
p.standaloneDocument = document
|
||||
}
|
||||
func (p *schemaPool) parseReferencesRecursive(document interface{}, ref gojsonreference.JsonReference, draft *Draft) error {
|
||||
// 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
|
||||
|
||||
func (p *schemaPool) GetStandaloneDocument() (document interface{}) {
|
||||
return p.standaloneDocument
|
||||
// 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, draft)
|
||||
}
|
||||
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 {
|
||||
if _, ok := p.schemaPoolDocuments[localRef.String()]; ok {
|
||||
return fmt.Errorf("Reference already exists: \"%s\"", localRef.String())
|
||||
}
|
||||
p.schemaPoolDocuments[localRef.String()] = &schemaPoolDocument{Document: document, Draft: draft}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, draft)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p.parseReferencesRecursive(v, *localRef, draft)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *schemaPool) GetDocument(reference gojsonreference.JsonReference) (*schemaPoolDocument, error) {
|
||||
|
||||
var (
|
||||
spd *schemaPoolDocument
|
||||
draft *Draft
|
||||
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
|
||||
}
|
||||
|
||||
// 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, Draft: cachedSpd.Draft}
|
||||
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, true)
|
||||
|
||||
return spd, nil
|
||||
_, draft, _ = parseSchemaURL(document)
|
||||
|
||||
// resolve the potential fragment and also cache it
|
||||
document, _, err = reference.GetPointer().Get(document)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &schemaPoolDocument{Document: document, Draft: draft}, 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
|
||||
}
|
||||
}
|
||||
|
|
67
vendor/github.com/xeipuuv/gojsonschema/subSchema.go
generated
vendored
67
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,23 @@ 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 {
|
||||
draft *Draft
|
||||
|
||||
// basic subSchema meta properties
|
||||
id *string
|
||||
id *gojsonreference.JsonReference
|
||||
title *string
|
||||
description *string
|
||||
|
||||
|
@ -86,23 +95,19 @@ 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
|
||||
exclusiveMaximum bool
|
||||
minimum *float64
|
||||
exclusiveMinimum bool
|
||||
multipleOf *big.Rat
|
||||
maximum *big.Rat
|
||||
exclusiveMaximum *big.Rat
|
||||
minimum *big.Rat
|
||||
exclusiveMinimum *big.Rat
|
||||
|
||||
// validation : string
|
||||
minLength *int
|
||||
|
@ -118,27 +123,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 +178,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 +202,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 +228,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)
|
||||
}
|
||||
|
|
72
vendor/github.com/xeipuuv/gojsonschema/utils.go
generated
vendored
72
vendor/github.com/xeipuuv/gojsonschema/utils.go
generated
vendored
|
@ -29,17 +29,23 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func isKind(what interface{}, kind reflect.Kind) bool {
|
||||
func isKind(what interface{}, kinds ...reflect.Kind) bool {
|
||||
target := what
|
||||
if isJsonNumber(what) {
|
||||
// JSON Numbers are strings!
|
||||
target = *mustBeNumber(what)
|
||||
}
|
||||
return reflect.ValueOf(target).Kind() == kind
|
||||
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 {
|
||||
|
@ -56,6 +62,16 @@ func isStringInSlice(s []string, what string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// indexStringInSlice returns the index of the first instance of 'what' in s or -1 if it is not found in s.
|
||||
func indexStringInSlice(s []string, what string) int {
|
||||
for i := range s {
|
||||
if s[i] == what {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func marshalToJsonString(value interface{}) (*string, error) {
|
||||
|
||||
mBytes, err := json.Marshal(value)
|
||||
|
@ -67,6 +83,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) {
|
||||
|
@ -78,21 +116,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)
|
||||
|
||||
f64, errFloat64 := jsonNumber.Float64()
|
||||
s64 := strconv.FormatFloat(f64, 'f', -1, 64)
|
||||
_, errInt64 := strconv.ParseInt(s64, 10, 64)
|
||||
bigFloat, isValidNumber := new(big.Rat).SetString(string(jsonNumber))
|
||||
|
||||
isValidFloat64 = errFloat64 == nil
|
||||
isValidInt64 = errInt64 == nil
|
||||
|
||||
_, errInt32 := strconv.ParseInt(s64, 10, 32)
|
||||
isValidInt32 = isValidInt64 && errInt32 == nil
|
||||
|
||||
return
|
||||
return isValidNumber && bigFloat.IsInt()
|
||||
|
||||
}
|
||||
|
||||
|
@ -117,9 +147,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 {
|
||||
|
@ -138,15 +168,13 @@ func mustBeInteger(what interface{}) *int {
|
|||
return nil
|
||||
}
|
||||
|
||||
func mustBeNumber(what interface{}) *float64 {
|
||||
func mustBeNumber(what interface{}) *big.Rat {
|
||||
|
||||
if isJsonNumber(what) {
|
||||
|
||||
number := what.(json.Number)
|
||||
float64Value, err := number.Float64()
|
||||
|
||||
if err == nil {
|
||||
return &float64Value
|
||||
float64Value, success := new(big.Rat).SetString(string(number))
|
||||
if success {
|
||||
return float64Value
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
|
303
vendor/github.com/xeipuuv/gojsonschema/validation.go
generated
vendored
303
vendor/github.com/xeipuuv/gojsonschema/validation.go
generated
vendored
|
@ -27,6 +27,7 @@ package gojsonschema
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
@ -60,24 +61,27 @@ func (v *Schema) Validate(l JSONLoader) (*Result, error) {
|
|||
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,7 +443,7 @@ 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())
|
||||
|
@ -417,7 +455,7 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
|
|||
// 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)
|
||||
}
|
||||
|
@ -428,7 +466,7 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
|
|||
|
||||
// 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)
|
||||
subContext := NewJsonContext(strconv.Itoa(i), context)
|
||||
validationResult := currentSubSchema.itemsChildren[i].subValidateWithContext(value[i], subContext)
|
||||
result.mergeErrors(validationResult)
|
||||
}
|
||||
|
@ -440,12 +478,12 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
|
|||
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)
|
||||
}
|
||||
|
@ -457,7 +495,7 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
|
|||
// minItems & maxItems
|
||||
if currentSubSchema.minItems != nil {
|
||||
if nbValues < int(*currentSubSchema.minItems) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(ArrayMinItemsError),
|
||||
context,
|
||||
value,
|
||||
|
@ -467,7 +505,7 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
|
|||
}
|
||||
if currentSubSchema.maxItems != nil {
|
||||
if nbValues > int(*currentSubSchema.maxItems) {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(ArrayMaxItemsError),
|
||||
context,
|
||||
value,
|
||||
|
@ -479,27 +517,59 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
|
|||
// uniqueItems:
|
||||
if currentSubSchema.uniqueItems {
|
||||
var stringifiedItems []string
|
||||
for _, v := range value {
|
||||
vString, err := marshalToJsonString(v)
|
||||
for j, v := range value {
|
||||
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(
|
||||
if i := indexStringInSlice(stringifiedItems, *vString); i > -1 {
|
||||
result.addInternalError(
|
||||
new(ItemsMustBeUniqueError),
|
||||
context,
|
||||
value,
|
||||
ErrorDetails{"type": TYPE_ARRAY},
|
||||
ErrorDetails{"type": TYPE_ARRAY, "i": i, "j": j},
|
||||
)
|
||||
}
|
||||
stringifiedItems = append(stringifiedItems, *vString)
|
||||
}
|
||||
}
|
||||
|
||||
// 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())
|
||||
|
@ -509,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,
|
||||
|
@ -519,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,
|
||||
|
@ -534,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,
|
||||
|
@ -565,7 +635,7 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
|
|||
if found {
|
||||
|
||||
if pp_has && !pp_match {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(AdditionalPropertyNotAllowedError),
|
||||
context,
|
||||
value[pk],
|
||||
|
@ -576,7 +646,7 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
|
|||
} else {
|
||||
|
||||
if !pp_has || !pp_match {
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(AdditionalPropertyNotAllowedError),
|
||||
context,
|
||||
value[pk],
|
||||
|
@ -628,7 +698,7 @@ func (v *subSchema) validateObject(currentSubSchema *subSchema, value map[string
|
|||
|
||||
if pp_has && !pp_match {
|
||||
|
||||
result.addError(
|
||||
result.addInternalError(
|
||||
new(InvalidPropertyPatternError),
|
||||
context,
|
||||
value[pk],
|
||||
|
@ -642,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())
|
||||
|
@ -659,12 +744,10 @@ 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() {
|
||||
validatedkey = true
|
||||
}
|
||||
validatedkey = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -677,7 +760,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) {
|
||||
|
@ -699,7 +782,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,
|
||||
|
@ -709,7 +792,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,
|
||||
|
@ -721,7 +804,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,
|
||||
|
@ -734,7 +817,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,
|
||||
|
@ -746,7 +829,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) {
|
||||
|
@ -759,72 +842,82 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{
|
|||
}
|
||||
|
||||
number := value.(json.Number)
|
||||
float64Value, _ := number.Float64()
|
||||
float64Value, _ := new(big.Rat).SetString(string(number))
|
||||
|
||||
// multipleOf:
|
||||
if currentSubSchema.multipleOf != nil {
|
||||
|
||||
if !isFloat64AnInteger(float64Value / *currentSubSchema.multipleOf) {
|
||||
result.addError(
|
||||
if q := new(big.Rat).Quo(float64Value, currentSubSchema.multipleOf); !q.IsInt() {
|
||||
result.addInternalError(
|
||||
new(MultipleOfError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{"multiple": *currentSubSchema.multipleOf},
|
||||
ErrorDetails{"multiple": new(big.Float).SetRat(currentSubSchema.multipleOf)},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//maximum & exclusiveMaximum:
|
||||
if currentSubSchema.maximum != nil {
|
||||
if currentSubSchema.exclusiveMaximum {
|
||||
if float64Value >= *currentSubSchema.maximum {
|
||||
result.addError(
|
||||
new(NumberLTError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{
|
||||
"max": resultErrorFormatNumber(*currentSubSchema.maximum),
|
||||
},
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if float64Value > *currentSubSchema.maximum {
|
||||
result.addError(
|
||||
new(NumberLTEError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{
|
||||
"max": resultErrorFormatNumber(*currentSubSchema.maximum),
|
||||
},
|
||||
)
|
||||
}
|
||||
if float64Value.Cmp(currentSubSchema.maximum) == 1 {
|
||||
result.addInternalError(
|
||||
new(NumberLTEError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{
|
||||
"max": currentSubSchema.maximum,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
if currentSubSchema.exclusiveMaximum != nil {
|
||||
if float64Value.Cmp(currentSubSchema.exclusiveMaximum) >= 0 {
|
||||
result.addInternalError(
|
||||
new(NumberLTError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{
|
||||
"max": currentSubSchema.exclusiveMaximum,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//minimum & exclusiveMinimum:
|
||||
if currentSubSchema.minimum != nil {
|
||||
if currentSubSchema.exclusiveMinimum {
|
||||
if float64Value <= *currentSubSchema.minimum {
|
||||
result.addError(
|
||||
new(NumberGTError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{
|
||||
"min": resultErrorFormatNumber(*currentSubSchema.minimum),
|
||||
},
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if float64Value < *currentSubSchema.minimum {
|
||||
result.addError(
|
||||
new(NumberGTEError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{
|
||||
"min": resultErrorFormatNumber(*currentSubSchema.minimum),
|
||||
},
|
||||
)
|
||||
}
|
||||
if float64Value.Cmp(currentSubSchema.minimum) == -1 {
|
||||
result.addInternalError(
|
||||
new(NumberGTEError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{
|
||||
"min": currentSubSchema.minimum,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
if currentSubSchema.exclusiveMinimum != nil {
|
||||
if float64Value.Cmp(currentSubSchema.exclusiveMinimum) <= 0 {
|
||||
// if float64Value <= *currentSubSchema.minimum {
|
||||
result.addInternalError(
|
||||
new(NumberGTError),
|
||||
context,
|
||||
resultErrorFormatJsonNumber(number),
|
||||
ErrorDetails{
|
||||
"min": currentSubSchema.exclusiveMinimum,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// format
|
||||
if currentSubSchema.format != "" {
|
||||
if !FormatCheckers.IsFormat(currentSubSchema.format, float64Value) {
|
||||
result.addInternalError(
|
||||
new(DoesNotMatchFormatError),
|
||||
context,
|
||||
value,
|
||||
ErrorDetails{"format": currentSubSchema.format},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue