...

Source file src/github.com/xeipuuv/gojsonschema/errors.go

Documentation: github.com/xeipuuv/gojsonschema

     1  package gojsonschema
     2  
     3  import (
     4  	"bytes"
     5  	"sync"
     6  	"text/template"
     7  )
     8  
     9  var errorTemplates = errorTemplate{template.New("errors-new"), sync.RWMutex{}}
    10  
    11  // template.Template is not thread-safe for writing, so some locking is done
    12  // sync.RWMutex is used for efficiently locking when new templates are created
    13  type errorTemplate struct {
    14  	*template.Template
    15  	sync.RWMutex
    16  }
    17  
    18  type (
    19  
    20  	// FalseError. ErrorDetails: -
    21  	FalseError struct {
    22  		ResultErrorFields
    23  	}
    24  
    25  	// RequiredError indicates that a required field is missing
    26  	// ErrorDetails: property string
    27  	RequiredError struct {
    28  		ResultErrorFields
    29  	}
    30  
    31  	// InvalidTypeError indicates that a field has the incorrect type
    32  	// ErrorDetails: expected, given
    33  	InvalidTypeError struct {
    34  		ResultErrorFields
    35  	}
    36  
    37  	// NumberAnyOfError is produced in case of a failing "anyOf" validation
    38  	// ErrorDetails: -
    39  	NumberAnyOfError struct {
    40  		ResultErrorFields
    41  	}
    42  
    43  	// NumberOneOfError is produced in case of a failing "oneOf" validation
    44  	// ErrorDetails: -
    45  	NumberOneOfError struct {
    46  		ResultErrorFields
    47  	}
    48  
    49  	// NumberAllOfError is produced in case of a failing "allOf" validation
    50  	// ErrorDetails: -
    51  	NumberAllOfError struct {
    52  		ResultErrorFields
    53  	}
    54  
    55  	// NumberNotError is produced if a "not" validation failed
    56  	// ErrorDetails: -
    57  	NumberNotError struct {
    58  		ResultErrorFields
    59  	}
    60  
    61  	// MissingDependencyError is produced in case of a "missing dependency" problem
    62  	// ErrorDetails: dependency
    63  	MissingDependencyError struct {
    64  		ResultErrorFields
    65  	}
    66  
    67  	// InternalError indicates an internal error
    68  	// ErrorDetails: error
    69  	InternalError struct {
    70  		ResultErrorFields
    71  	}
    72  
    73  	// ConstError indicates a const error
    74  	// ErrorDetails: allowed
    75  	ConstError struct {
    76  		ResultErrorFields
    77  	}
    78  
    79  	// EnumError indicates an enum error
    80  	// ErrorDetails: allowed
    81  	EnumError struct {
    82  		ResultErrorFields
    83  	}
    84  
    85  	// ArrayNoAdditionalItemsError is produced if additional items were found, but not allowed
    86  	// ErrorDetails: -
    87  	ArrayNoAdditionalItemsError struct {
    88  		ResultErrorFields
    89  	}
    90  
    91  	// ArrayMinItemsError is produced if an array contains less items than the allowed minimum
    92  	// ErrorDetails: min
    93  	ArrayMinItemsError struct {
    94  		ResultErrorFields
    95  	}
    96  
    97  	// ArrayMaxItemsError is produced if an array contains more items than the allowed maximum
    98  	// ErrorDetails: max
    99  	ArrayMaxItemsError struct {
   100  		ResultErrorFields
   101  	}
   102  
   103  	// ItemsMustBeUniqueError is produced if an array requires unique items, but contains non-unique items
   104  	// ErrorDetails: type, i, j
   105  	ItemsMustBeUniqueError struct {
   106  		ResultErrorFields
   107  	}
   108  
   109  	// ArrayContainsError is produced if an array contains invalid items
   110  	// ErrorDetails:
   111  	ArrayContainsError struct {
   112  		ResultErrorFields
   113  	}
   114  
   115  	// ArrayMinPropertiesError is produced if an object contains less properties than the allowed minimum
   116  	// ErrorDetails: min
   117  	ArrayMinPropertiesError struct {
   118  		ResultErrorFields
   119  	}
   120  
   121  	// ArrayMaxPropertiesError is produced if an object contains more properties than the allowed maximum
   122  	// ErrorDetails: max
   123  	ArrayMaxPropertiesError struct {
   124  		ResultErrorFields
   125  	}
   126  
   127  	// AdditionalPropertyNotAllowedError is produced if an object has additional properties, but not allowed
   128  	// ErrorDetails: property
   129  	AdditionalPropertyNotAllowedError struct {
   130  		ResultErrorFields
   131  	}
   132  
   133  	// InvalidPropertyPatternError is produced if an pattern was found
   134  	// ErrorDetails: property, pattern
   135  	InvalidPropertyPatternError struct {
   136  		ResultErrorFields
   137  	}
   138  
   139  	// InvalidPropertyNameError is produced if an invalid-named property was found
   140  	// ErrorDetails: property
   141  	InvalidPropertyNameError struct {
   142  		ResultErrorFields
   143  	}
   144  
   145  	// StringLengthGTEError is produced if a string is shorter than the minimum required length
   146  	// ErrorDetails: min
   147  	StringLengthGTEError struct {
   148  		ResultErrorFields
   149  	}
   150  
   151  	// StringLengthLTEError is produced if a string is longer than the maximum allowed length
   152  	// ErrorDetails: max
   153  	StringLengthLTEError struct {
   154  		ResultErrorFields
   155  	}
   156  
   157  	// DoesNotMatchPatternError is produced if a string does not match the defined pattern
   158  	// ErrorDetails: pattern
   159  	DoesNotMatchPatternError struct {
   160  		ResultErrorFields
   161  	}
   162  
   163  	// DoesNotMatchFormatError is produced if a string does not match the defined format
   164  	// ErrorDetails: format
   165  	DoesNotMatchFormatError struct {
   166  		ResultErrorFields
   167  	}
   168  
   169  	// MultipleOfError is produced if a number is not a multiple of the defined multipleOf
   170  	// ErrorDetails: multiple
   171  	MultipleOfError struct {
   172  		ResultErrorFields
   173  	}
   174  
   175  	// NumberGTEError is produced if a number is lower than the allowed minimum
   176  	// ErrorDetails: min
   177  	NumberGTEError struct {
   178  		ResultErrorFields
   179  	}
   180  
   181  	// NumberGTError is produced if a number is lower than, or equal to the specified minimum, and exclusiveMinimum is set
   182  	// ErrorDetails: min
   183  	NumberGTError struct {
   184  		ResultErrorFields
   185  	}
   186  
   187  	// NumberLTEError is produced if a number is higher than the allowed maximum
   188  	// ErrorDetails: max
   189  	NumberLTEError struct {
   190  		ResultErrorFields
   191  	}
   192  
   193  	// NumberLTError is produced if a number is higher than, or equal to the specified maximum, and exclusiveMaximum is set
   194  	// ErrorDetails: max
   195  	NumberLTError struct {
   196  		ResultErrorFields
   197  	}
   198  
   199  	// ConditionThenError is produced if a condition's "then" validation is invalid
   200  	// ErrorDetails: -
   201  	ConditionThenError struct {
   202  		ResultErrorFields
   203  	}
   204  
   205  	// ConditionElseError is produced if a condition's "else" condition is invalid
   206  	// ErrorDetails: -
   207  	ConditionElseError struct {
   208  		ResultErrorFields
   209  	}
   210  )
   211  
   212  // newError takes a ResultError type and sets the type, context, description, details, value, and field
   213  func newError(err ResultError, context *JsonContext, value interface{}, locale locale, details ErrorDetails) {
   214  	var t string
   215  	var d string
   216  	switch err.(type) {
   217  	case *FalseError:
   218  		t = "false"
   219  		d = locale.False()
   220  	case *RequiredError:
   221  		t = "required"
   222  		d = locale.Required()
   223  	case *InvalidTypeError:
   224  		t = "invalid_type"
   225  		d = locale.InvalidType()
   226  	case *NumberAnyOfError:
   227  		t = "number_any_of"
   228  		d = locale.NumberAnyOf()
   229  	case *NumberOneOfError:
   230  		t = "number_one_of"
   231  		d = locale.NumberOneOf()
   232  	case *NumberAllOfError:
   233  		t = "number_all_of"
   234  		d = locale.NumberAllOf()
   235  	case *NumberNotError:
   236  		t = "number_not"
   237  		d = locale.NumberNot()
   238  	case *MissingDependencyError:
   239  		t = "missing_dependency"
   240  		d = locale.MissingDependency()
   241  	case *InternalError:
   242  		t = "internal"
   243  		d = locale.Internal()
   244  	case *ConstError:
   245  		t = "const"
   246  		d = locale.Const()
   247  	case *EnumError:
   248  		t = "enum"
   249  		d = locale.Enum()
   250  	case *ArrayNoAdditionalItemsError:
   251  		t = "array_no_additional_items"
   252  		d = locale.ArrayNoAdditionalItems()
   253  	case *ArrayMinItemsError:
   254  		t = "array_min_items"
   255  		d = locale.ArrayMinItems()
   256  	case *ArrayMaxItemsError:
   257  		t = "array_max_items"
   258  		d = locale.ArrayMaxItems()
   259  	case *ItemsMustBeUniqueError:
   260  		t = "unique"
   261  		d = locale.Unique()
   262  	case *ArrayContainsError:
   263  		t = "contains"
   264  		d = locale.ArrayContains()
   265  	case *ArrayMinPropertiesError:
   266  		t = "array_min_properties"
   267  		d = locale.ArrayMinProperties()
   268  	case *ArrayMaxPropertiesError:
   269  		t = "array_max_properties"
   270  		d = locale.ArrayMaxProperties()
   271  	case *AdditionalPropertyNotAllowedError:
   272  		t = "additional_property_not_allowed"
   273  		d = locale.AdditionalPropertyNotAllowed()
   274  	case *InvalidPropertyPatternError:
   275  		t = "invalid_property_pattern"
   276  		d = locale.InvalidPropertyPattern()
   277  	case *InvalidPropertyNameError:
   278  		t = "invalid_property_name"
   279  		d = locale.InvalidPropertyName()
   280  	case *StringLengthGTEError:
   281  		t = "string_gte"
   282  		d = locale.StringGTE()
   283  	case *StringLengthLTEError:
   284  		t = "string_lte"
   285  		d = locale.StringLTE()
   286  	case *DoesNotMatchPatternError:
   287  		t = "pattern"
   288  		d = locale.DoesNotMatchPattern()
   289  	case *DoesNotMatchFormatError:
   290  		t = "format"
   291  		d = locale.DoesNotMatchFormat()
   292  	case *MultipleOfError:
   293  		t = "multiple_of"
   294  		d = locale.MultipleOf()
   295  	case *NumberGTEError:
   296  		t = "number_gte"
   297  		d = locale.NumberGTE()
   298  	case *NumberGTError:
   299  		t = "number_gt"
   300  		d = locale.NumberGT()
   301  	case *NumberLTEError:
   302  		t = "number_lte"
   303  		d = locale.NumberLTE()
   304  	case *NumberLTError:
   305  		t = "number_lt"
   306  		d = locale.NumberLT()
   307  	case *ConditionThenError:
   308  		t = "condition_then"
   309  		d = locale.ConditionThen()
   310  	case *ConditionElseError:
   311  		t = "condition_else"
   312  		d = locale.ConditionElse()
   313  	}
   314  
   315  	err.SetType(t)
   316  	err.SetContext(context)
   317  	err.SetValue(value)
   318  	err.SetDetails(details)
   319  	err.SetDescriptionFormat(d)
   320  	details["field"] = err.Field()
   321  
   322  	if _, exists := details["context"]; !exists && context != nil {
   323  		details["context"] = context.String()
   324  	}
   325  
   326  	err.SetDescription(formatErrorDescription(err.DescriptionFormat(), details))
   327  }
   328  
   329  // formatErrorDescription takes a string in the default text/template
   330  // format and converts it to a string with replacements. The fields come
   331  // from the ErrorDetails struct and vary for each type of error.
   332  func formatErrorDescription(s string, details ErrorDetails) string {
   333  
   334  	var tpl *template.Template
   335  	var descrAsBuffer bytes.Buffer
   336  	var err error
   337  
   338  	errorTemplates.RLock()
   339  	tpl = errorTemplates.Lookup(s)
   340  	errorTemplates.RUnlock()
   341  
   342  	if tpl == nil {
   343  		errorTemplates.Lock()
   344  		tpl = errorTemplates.New(s)
   345  
   346  		if ErrorTemplateFuncs != nil {
   347  			tpl.Funcs(ErrorTemplateFuncs)
   348  		}
   349  
   350  		tpl, err = tpl.Parse(s)
   351  		errorTemplates.Unlock()
   352  
   353  		if err != nil {
   354  			return err.Error()
   355  		}
   356  	}
   357  
   358  	err = tpl.Execute(&descrAsBuffer, details)
   359  	if err != nil {
   360  		return err.Error()
   361  	}
   362  
   363  	return descrAsBuffer.String()
   364  }
   365  

View as plain text