Allow external use of AddError
diff --git a/.gitignore b/.gitignore
index c1e0636..4c60981 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
*.sw[nop]
+*.iml
diff --git a/errors.go b/errors.go
index 58cb01f..072ce25 100644
--- a/errors.go
+++ b/errors.go
@@ -254,11 +254,15 @@
err.SetDetails(details)
details["field"] = err.Field()
+ if err.DescriptionFormat() == "" && d != "" {
+ err.SetDescriptionFormat(d)
+ }
+
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
diff --git a/jsonContext.go b/jsonContext.go
index fcc8d9d..1c58656 100644
--- a/jsonContext.go
+++ b/jsonContext.go
@@ -32,7 +32,7 @@
tail *jsonContext
}
-func newJsonContext(head string, tail *jsonContext) *jsonContext {
+func NewJsonContext(head string, tail *jsonContext) *jsonContext {
return &jsonContext{head, tail}
}
diff --git a/result.go b/result.go
index 6ad56ae..d21e53f 100644
--- a/result.go
+++ b/result.go
@@ -44,6 +44,8 @@
Context() *jsonContext
SetDescription(string)
Description() string
+ SetDescriptionFormat(string)
+ DescriptionFormat() string
SetValue(interface{})
Value() interface{}
SetDetails(ErrorDetails)
@@ -55,11 +57,12 @@
// 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 {
@@ -106,6 +109,14 @@
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 +166,7 @@
return v.errors
}
-func (v *Result) addError(err ResultError, context *jsonContext, value interface{}, details ErrorDetails) {
+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
diff --git a/validation.go b/validation.go
index 664da21..3a1ae26 100644
--- a/validation.go
+++ b/validation.go
@@ -64,7 +64,7 @@
// 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
@@ -94,7 +94,7 @@
// Check for null value
if currentNode == nil {
if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_NULL) {
- result.addError(
+ result.addInternalError(
new(InvalidTypeError),
context,
currentNode,
@@ -126,7 +126,7 @@
givenType = TYPE_NUMBER
}
- result.addError(
+ result.addInternalError(
new(InvalidTypeError),
context,
currentNode,
@@ -155,7 +155,7 @@
case reflect.Slice:
if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_ARRAY) {
- result.addError(
+ result.addInternalError(
new(InvalidTypeError),
context,
currentNode,
@@ -178,7 +178,7 @@
case reflect.Map:
if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_OBJECT) {
- result.addError(
+ result.addInternalError(
new(InvalidTypeError),
context,
currentNode,
@@ -203,7 +203,7 @@
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)
}
}
@@ -213,7 +213,7 @@
case reflect.Bool:
if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_BOOLEAN) {
- result.addError(
+ result.addInternalError(
new(InvalidTypeError),
context,
currentNode,
@@ -235,7 +235,7 @@
case reflect.String:
if currentSubSchema.types.IsTyped() && !currentSubSchema.types.Contains(TYPE_STRING) {
- result.addError(
+ result.addInternalError(
new(InvalidTypeError),
context,
currentNode,
@@ -288,7 +288,7 @@
}
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
@@ -314,7 +314,7 @@
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
@@ -337,14 +337,14 @@
}
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{})
}
}
@@ -357,7 +357,7 @@
case []string:
for _, dependOnKey := range dependency {
if _, dependencyResolved := currentNode.(map[string]interface{})[dependOnKey]; !dependencyResolved {
- result.addError(
+ result.addInternalError(
new(MissingDependencyError),
context,
currentNode,
@@ -380,14 +380,14 @@
if currentSubSchema._then != nil && validationResultIf.Valid() {
validationResultThen := currentSubSchema._then.subValidateWithContext(currentNode, context)
if !validationResultThen.Valid() {
- result.addError(new(ConditionThenError), context, currentNode, ErrorDetails{})
+ 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.addError(new(ConditionElseError), context, currentNode, ErrorDetails{})
+ result.addInternalError(new(ConditionElseError), context, currentNode, ErrorDetails{})
result.mergeErrors(validationResultElse)
}
}
@@ -407,10 +407,10 @@
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,
@@ -436,7 +436,7 @@
// 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)
}
@@ -447,7 +447,7 @@
// 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)
}
@@ -459,12 +459,12 @@
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)
}
@@ -476,7 +476,7 @@
// minItems & maxItems
if currentSubSchema.minItems != nil {
if nbValues < int(*currentSubSchema.minItems) {
- result.addError(
+ result.addInternalError(
new(ArrayMinItemsError),
context,
value,
@@ -486,7 +486,7 @@
}
if currentSubSchema.maxItems != nil {
if nbValues > int(*currentSubSchema.maxItems) {
- result.addError(
+ result.addInternalError(
new(ArrayMaxItemsError),
context,
value,
@@ -501,10 +501,10 @@
for _, v := range value {
vString, err := marshalToJsonString(v)
if err != nil {
- result.addError(new(InternalError), context, value, ErrorDetails{"err": err})
+ result.addInternalError(new(InternalError), context, value, ErrorDetails{"err": err})
}
if isStringInSlice(stringifiedItems, *vString) {
- result.addError(
+ result.addInternalError(
new(ItemsMustBeUniqueError),
context,
value,
@@ -528,7 +528,7 @@
// minProperties & maxProperties:
if currentSubSchema.minProperties != nil {
if len(value) < int(*currentSubSchema.minProperties) {
- result.addError(
+ result.addInternalError(
new(ArrayMinPropertiesError),
context,
value,
@@ -538,7 +538,7 @@
}
if currentSubSchema.maxProperties != nil {
if len(value) > int(*currentSubSchema.maxProperties) {
- result.addError(
+ result.addInternalError(
new(ArrayMaxPropertiesError),
context,
value,
@@ -553,7 +553,7 @@
if ok {
result.incrementScore()
} else {
- result.addError(
+ result.addInternalError(
new(RequiredError),
context,
value,
@@ -584,7 +584,7 @@
if found {
if pp_has && !pp_match {
- result.addError(
+ result.addInternalError(
new(AdditionalPropertyNotAllowedError),
context,
value[pk],
@@ -595,7 +595,7 @@
} else {
if !pp_has || !pp_match {
- result.addError(
+ result.addInternalError(
new(AdditionalPropertyNotAllowedError),
context,
value[pk],
@@ -647,7 +647,7 @@
if pp_has && !pp_match {
- result.addError(
+ result.addInternalError(
new(InvalidPropertyPatternError),
context,
value[pk],
@@ -678,7 +678,7 @@
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() {
@@ -718,7 +718,7 @@
// minLength & maxLength:
if currentSubSchema.minLength != nil {
if utf8.RuneCount([]byte(stringValue)) < int(*currentSubSchema.minLength) {
- result.addError(
+ result.addInternalError(
new(StringLengthGTEError),
context,
value,
@@ -728,7 +728,7 @@
}
if currentSubSchema.maxLength != nil {
if utf8.RuneCount([]byte(stringValue)) > int(*currentSubSchema.maxLength) {
- result.addError(
+ result.addInternalError(
new(StringLengthLTEError),
context,
value,
@@ -740,7 +740,7 @@
// pattern:
if currentSubSchema.pattern != nil {
if !currentSubSchema.pattern.MatchString(stringValue) {
- result.addError(
+ result.addInternalError(
new(DoesNotMatchPatternError),
context,
value,
@@ -753,7 +753,7 @@
// format
if currentSubSchema.format != "" {
if !FormatCheckers.IsFormat(currentSubSchema.format, stringValue) {
- result.addError(
+ result.addInternalError(
new(DoesNotMatchFormatError),
context,
value,
@@ -784,7 +784,7 @@
if currentSubSchema.multipleOf != nil {
if q := new(big.Float).Quo(float64Value, currentSubSchema.multipleOf); !q.IsInt() {
- result.addError(
+ result.addInternalError(
new(MultipleOfError),
context,
resultErrorFormatJsonNumber(number),
@@ -797,7 +797,7 @@
if currentSubSchema.maximum != nil {
if currentSubSchema.exclusiveMaximum {
if float64Value.Cmp(currentSubSchema.maximum) >= 0 {
- result.addError(
+ result.addInternalError(
new(NumberLTError),
context,
resultErrorFormatJsonNumber(number),
@@ -808,7 +808,7 @@
}
} else {
if float64Value.Cmp(currentSubSchema.maximum) == 1 {
- result.addError(
+ result.addInternalError(
new(NumberLTEError),
context,
resultErrorFormatJsonNumber(number),
@@ -825,7 +825,7 @@
if currentSubSchema.exclusiveMinimum {
if float64Value.Cmp(currentSubSchema.minimum) <= 0 {
// if float64Value <= *currentSubSchema.minimum {
- result.addError(
+ result.addInternalError(
new(NumberGTError),
context,
resultErrorFormatJsonNumber(number),
@@ -836,7 +836,7 @@
}
} else {
if float64Value.Cmp(currentSubSchema.minimum) == -1 {
- result.addError(
+ result.addInternalError(
new(NumberGTEError),
context,
resultErrorFormatJsonNumber(number),
@@ -851,7 +851,7 @@
// format
if currentSubSchema.format != "" {
if !FormatCheckers.IsFormat(currentSubSchema.format, float64Value) {
- result.addError(
+ result.addInternalError(
new(DoesNotMatchFormatError),
context,
value,