123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- // Copyright 2015 xeipuuv ( https://github.com/xeipuuv )
- //
- // 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.
- // author xeipuuv
- // author-github https://github.com/xeipuuv
- // author-mail xeipuuv@gmail.com
- //
- // repository-name gojsonschema
- // repository-desc An implementation of JSON Schema, based on IETF's draft v4 - Go language.
- //
- // description Result and ResultError implementations.
- //
- // created 01-01-2015
- package gojsonschema
- import (
- "fmt"
- "strings"
- )
- type (
- // ErrorDetails is a map of details specific to each error.
- // While the values will vary, every error will contain a "field" value
- ErrorDetails map[string]interface{}
- // ResultError is the interface that library errors must implement
- ResultError interface {
- // Field returns the field name without the root context
- // i.e. firstName or person.firstName instead of (root).firstName or (root).person.firstName
- Field() string
- // SetType sets the error-type
- SetType(string)
- // Type returns the error-type
- Type() string
- // SetContext sets the JSON-context for the error
- SetContext(*JsonContext)
- // Context returns the JSON-context of the error
- Context() *JsonContext
- // SetDescription sets a description for the error
- SetDescription(string)
- // Description returns the description of the error
- Description() string
- // SetDescriptionFormat sets the format for the description in the default text/template format
- SetDescriptionFormat(string)
- // DescriptionFormat returns the format for the description in the default text/template format
- DescriptionFormat() string
- // SetValue sets the value related to the error
- SetValue(interface{})
- // Value returns the value related to the error
- Value() interface{}
- // SetDetails sets the details specific to the error
- SetDetails(ErrorDetails)
- // Details returns details about the error
- Details() ErrorDetails
- // String returns a string representation of the error
- String() string
- }
- // ResultErrorFields holds the fields for each ResultError implementation.
- // ResultErrorFields implements the ResultError interface, so custom errors
- // can be defined by just embedding this type
- ResultErrorFields struct {
- errorType string // A string with the type of error (i.e. invalid_type)
- context *JsonContext // Tree like notation of the part that failed the validation. ex (root).a.b ...
- description string // A human readable error message
- 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 holds the result of a validation
- Result struct {
- errors []ResultError
- // Scores how well the validation matched. Useful in generating
- // better error messages for anyOf and oneOf.
- score int
- }
- )
- // Field returns 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 {
- return strings.TrimPrefix(v.context.String(), STRING_ROOT_SCHEMA_PROPERTY+".")
- }
- // SetType sets the error-type
- func (v *ResultErrorFields) SetType(errorType string) {
- v.errorType = errorType
- }
- // Type returns the error-type
- func (v *ResultErrorFields) Type() string {
- return v.errorType
- }
- // SetContext sets the JSON-context for the error
- func (v *ResultErrorFields) SetContext(context *JsonContext) {
- v.context = context
- }
- // Context returns the JSON-context of the error
- func (v *ResultErrorFields) Context() *JsonContext {
- return v.context
- }
- // SetDescription sets a description for the error
- func (v *ResultErrorFields) SetDescription(description string) {
- v.description = description
- }
- // Description returns the description of the error
- func (v *ResultErrorFields) Description() string {
- return v.description
- }
- // SetDescriptionFormat sets the format for the description in the default text/template format
- func (v *ResultErrorFields) SetDescriptionFormat(descriptionFormat string) {
- v.descriptionFormat = descriptionFormat
- }
- // DescriptionFormat returns the format for the description in the default text/template format
- func (v *ResultErrorFields) DescriptionFormat() string {
- return v.descriptionFormat
- }
- // SetValue sets the value related to the error
- func (v *ResultErrorFields) SetValue(value interface{}) {
- v.value = value
- }
- // Value returns the value related to the error
- func (v *ResultErrorFields) Value() interface{} {
- return v.value
- }
- // SetDetails sets the details specific to the error
- func (v *ResultErrorFields) SetDetails(details ErrorDetails) {
- v.details = details
- }
- // Details returns details about the error
- func (v *ResultErrorFields) Details() ErrorDetails {
- return v.details
- }
- // String returns a string representation of the error
- func (v ResultErrorFields) String() string {
- // as a fallback, the value is displayed go style
- valueString := fmt.Sprintf("%v", v.value)
- // marshal the go value value to json
- if v.value == nil {
- valueString = TYPE_NULL
- } else {
- if vs, err := marshalToJSONString(v.value); err == nil {
- if vs == nil {
- valueString = TYPE_NULL
- } else {
- valueString = *vs
- }
- }
- }
- return formatErrorDescription(Locale.ErrorFormat(), ErrorDetails{
- "context": v.context.String(),
- "description": v.description,
- "value": valueString,
- "field": v.Field(),
- })
- }
- // Valid indicates if no errors were found
- func (v *Result) Valid() bool {
- return len(v.errors) == 0
- }
- // Errors returns the errors that were found
- func (v *Result) Errors() []ResultError {
- return v.errors
- }
- // AddError appends 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
- }
- // Used to copy errors from a sub-schema to the main one
- func (v *Result) mergeErrors(otherResult *Result) {
- v.errors = append(v.errors, otherResult.Errors()...)
- v.score += otherResult.score
- }
- func (v *Result) incrementScore() {
- v.score++
- }
|