Skip to content

Commit

Permalink
errors: captures error message fields in struct
Browse files Browse the repository at this point in the history
closes Issue #44
  • Loading branch information
santhosh-tekuri committed Jan 12, 2023
1 parent 2dc9222 commit e8eeadf
Show file tree
Hide file tree
Showing 7 changed files with 465 additions and 96 deletions.
20 changes: 0 additions & 20 deletions compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,26 +371,6 @@ func (c *Compiler) compileMap(r *resource, stack []schemaRef, sref schemaRef, re

if e, ok := m["enum"]; ok {
s.Enum = e.([]interface{})
allPrimitives := true
for _, item := range s.Enum {
switch jsonType(item) {
case "object", "array":
allPrimitives = false
break
}
}
s.enumError = "enum failed"
if allPrimitives {
if len(s.Enum) == 1 {
s.enumError = fmt.Sprintf("value must be %#v", s.Enum[0])
} else {
strEnum := make([]string, len(s.Enum))
for i, item := range s.Enum {
strEnum[i] = fmt.Sprintf("%#v", item)
}
s.enumError = fmt.Sprintf("value must be one of %s", strings.Join(strEnum, ", "))
}
}
}

s.Minimum = loadRat("minimum")
Expand Down
11 changes: 7 additions & 4 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package jsonschema
import (
"fmt"
"strings"

"github.com/santhosh-tekuri/jsonschema/v5/msg"
)

// InvalidJSONTypeError is the error type returned by ValidateInterface.
Expand Down Expand Up @@ -69,7 +71,7 @@ type ValidationError struct {
KeywordLocation string // validation path of validating keyword or schema
AbsoluteKeywordLocation string // absolute location of validating keyword or schema
InstanceLocation string // location of the json value within the instance being validated
Message string // describes error
Message fmt.Stringer // captures the message and data used in constructing it
Causes []*ValidationError // nested validation errors
}

Expand All @@ -81,10 +83,11 @@ func (ve *ValidationError) add(causes ...error) error {
}

func (ve *ValidationError) causes(err error) error {
if err := err.(*ValidationError); err.Message == "" {
ve.Causes = err.Causes
var e = err.(*ValidationError)
if _, ok := e.Message.(msg.Empty); ok {
ve.Causes = e.Causes
} else {
ve.add(err)
ve.add(e)
}
return ve
}
Expand Down
11 changes: 10 additions & 1 deletion example_extension_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ func (powerOfCompiler) Compile(ctx jsonschema.CompilerContext, m map[string]inte
return nil, nil
}

type powerOfSchemaMsg struct {
got interface{}
want int64
}

func (m powerOfSchemaMsg) String() string {
return fmt.Sprintf("%v not powerOf %v", m.got, m.want)
}

type powerOfSchema int64

func (s powerOfSchema) Validate(ctx jsonschema.ValidationContext, v interface{}) error {
Expand All @@ -42,7 +51,7 @@ func (s powerOfSchema) Validate(ctx jsonschema.ValidationContext, v interface{})
n = n / pow
}
if n != 1 {
return ctx.Error("powerOf", "%v not powerOf %v", v, pow)
return ctx.Error("powerOf", powerOfSchemaMsg{got: v, want: pow})
}
return nil
default:
Expand Down
8 changes: 5 additions & 3 deletions extension.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package jsonschema

import "fmt"

// ExtCompiler compiles custom keyword(s) into ExtSchema.
type ExtCompiler interface {
// Compile compiles the custom keywords in schema m and returns its compiled representation.
Expand Down Expand Up @@ -75,7 +77,7 @@ type ValidationContext struct {
result validationResult
validate func(sch *Schema, schPath string, v interface{}, vpath string) error
validateInplace func(sch *Schema, schPath string) error
validationError func(keywordPath string, format string, a ...interface{}) *ValidationError
validationError func(keywordPath string, msg fmt.Stringer) *ValidationError
}

// EvaluatedProp marks given property of object as evaluated.
Expand Down Expand Up @@ -104,8 +106,8 @@ func (ctx ValidationContext) Validate(s *Schema, spath string, v interface{}, vp
// Error used to construct validation error by extensions.
//
// keywordPath is relative-json-pointer to keyword.
func (ctx ValidationContext) Error(keywordPath string, format string, a ...interface{}) *ValidationError {
return ctx.validationError(keywordPath, format, a...)
func (ctx ValidationContext) Error(keywordPath string, msg fmt.Stringer) *ValidationError {
return ctx.validationError(keywordPath, msg)
}

// Group is used by extensions to group multiple errors as causes to parent error.
Expand Down
Loading

0 comments on commit e8eeadf

Please sign in to comment.