|
24 | 24 |
|
25 | 25 | errSchema = errors.New("Input does not match the schema") |
26 | 26 |
|
| 27 | + // ErrSchemaInputNaN may be returned when validating a number |
27 | 28 | ErrSchemaInputNaN = errors.New("NaN is not allowed") |
| 29 | + // ErrSchemaInputInf may be returned when validating a number |
28 | 30 | ErrSchemaInputInf = errors.New("Inf is not allowed") |
29 | 31 | ) |
30 | 32 |
|
@@ -89,7 +91,7 @@ type Schema struct { |
89 | 91 | MinLength uint64 `json:"minLength,omitempty" yaml:"minLength,omitempty"` |
90 | 92 | MaxLength *uint64 `json:"maxLength,omitempty" yaml:"maxLength,omitempty"` |
91 | 93 | Pattern string `json:"pattern,omitempty" yaml:"pattern,omitempty"` |
92 | | - compiledPattern *compiledPattern |
| 94 | + compiledPattern *regexp.Regexp |
93 | 95 |
|
94 | 96 | // Array |
95 | 97 | MinItems uint64 `json:"minItems,omitempty" yaml:"minItems,omitempty"` |
@@ -225,11 +227,6 @@ func NewObjectSchema() *Schema { |
225 | 227 | } |
226 | 228 | } |
227 | 229 |
|
228 | | -type compiledPattern struct { |
229 | | - Regexp *regexp.Regexp |
230 | | - ErrReason string |
231 | | -} |
232 | | - |
233 | 230 | func (schema *Schema) WithNullable() *Schema { |
234 | 231 | schema.Nullable = true |
235 | 232 | return schema |
@@ -977,56 +974,66 @@ func (schema *Schema) visitJSONString(settings *schemaValidationSettings, value |
977 | 974 | } |
978 | 975 | } |
979 | 976 |
|
980 | | - // "format" and "pattern" |
981 | | - cp := schema.compiledPattern |
982 | | - if cp == nil { |
983 | | - pattern := schema.Pattern |
984 | | - if v := schema.Pattern; len(v) > 0 { |
985 | | - // Pattern |
986 | | - re, err := regexp.Compile(v) |
987 | | - if err != nil { |
988 | | - return fmt.Errorf("Error while compiling regular expression '%s': %v", pattern, err) |
989 | | - } |
990 | | - cp = &compiledPattern{ |
991 | | - Regexp: re, |
992 | | - ErrReason: "JSON string doesn't match the regular expression '" + v + "'", |
993 | | - } |
994 | | - schema.compiledPattern = cp |
995 | | - } else if v := schema.Format; len(v) > 0 { |
996 | | - // No pattern, but does have a format |
997 | | - if f, ok := SchemaStringFormats[v]; ok { |
998 | | - if f.regexp != nil && f.callback == nil { |
999 | | - schema.compiledPattern = &compiledPattern{ |
1000 | | - Regexp: f.regexp, |
1001 | | - ErrReason: "JSON string doesn't match the format '" + v + " (regular expression `" + f.regexp.String() + "`)'", |
1002 | | - } |
1003 | | - |
1004 | | - } else if f.regexp == nil && f.callback != nil { |
1005 | | - return f.callback(value) |
1006 | | - } else { |
1007 | | - return fmt.Errorf("corrupted entry %q in SchemaStringFormats", v) |
1008 | | - } |
1009 | | - } |
1010 | | - } |
1011 | | - } |
1012 | | - if cp != nil { |
1013 | | - if !cp.Regexp.MatchString(value) { |
1014 | | - field := "format" |
1015 | | - if schema.Pattern != "" { |
1016 | | - field = "pattern" |
1017 | | - } |
1018 | | - err := &SchemaError{ |
| 977 | + // "pattern" |
| 978 | + if pattern := schema.Pattern; pattern != "" && schema.compiledPattern == nil { |
| 979 | + var err error |
| 980 | + if schema.compiledPattern, err = regexp.Compile(pattern); err != nil { |
| 981 | + err = &SchemaError{ |
1019 | 982 | Value: value, |
1020 | 983 | Schema: schema, |
1021 | | - SchemaField: field, |
1022 | | - Reason: cp.ErrReason, |
| 984 | + SchemaField: "pattern", |
| 985 | + Reason: fmt.Sprintf("cannot compile pattern %q: %v", pattern, err), |
1023 | 986 | } |
1024 | 987 | if !settings.multiError { |
1025 | 988 | return err |
1026 | 989 | } |
1027 | 990 | me = append(me, err) |
1028 | 991 | } |
1029 | 992 | } |
| 993 | + if cp := schema.compiledPattern; cp != nil && !cp.MatchString(value) { |
| 994 | + err := &SchemaError{ |
| 995 | + Value: value, |
| 996 | + Schema: schema, |
| 997 | + SchemaField: "pattern", |
| 998 | + Reason: fmt.Sprintf("JSON string doesn't match the regular expression %q", schema.Pattern), |
| 999 | + } |
| 1000 | + if !settings.multiError { |
| 1001 | + return err |
| 1002 | + } |
| 1003 | + me = append(me, err) |
| 1004 | + } |
| 1005 | + |
| 1006 | + // "format" |
| 1007 | + var formatErr string |
| 1008 | + if format := schema.Format; format != "" { |
| 1009 | + if f, ok := SchemaStringFormats[format]; ok { |
| 1010 | + switch { |
| 1011 | + case f.regexp != nil && f.callback == nil: |
| 1012 | + if cp := f.regexp; !cp.MatchString(value) { |
| 1013 | + formatErr = fmt.Sprintf("JSON string doesn't match the format %q (regular expression %q)", format, cp.String()) |
| 1014 | + } |
| 1015 | + case f.regexp == nil && f.callback != nil: |
| 1016 | + if err := f.callback(value); err != nil { |
| 1017 | + formatErr = err.Error() |
| 1018 | + } |
| 1019 | + default: |
| 1020 | + formatErr = fmt.Sprintf("corrupted entry %q in SchemaStringFormats", format) |
| 1021 | + } |
| 1022 | + } |
| 1023 | + } |
| 1024 | + if formatErr != "" { |
| 1025 | + err := &SchemaError{ |
| 1026 | + Value: value, |
| 1027 | + Schema: schema, |
| 1028 | + SchemaField: "format", |
| 1029 | + Reason: formatErr, |
| 1030 | + } |
| 1031 | + if !settings.multiError { |
| 1032 | + return err |
| 1033 | + } |
| 1034 | + me = append(me, err) |
| 1035 | + |
| 1036 | + } |
1030 | 1037 |
|
1031 | 1038 | if len(me) > 0 { |
1032 | 1039 | return me |
|
0 commit comments