func equal(a json.Value, b json.Value) bool { switch x := a.(type) { case *json.Array: b, ok := b.(*json.Array) if !ok { return false } if len(x.Value) != len(b.Value) { return false } for i, item := range x.Value { if !equal(item, b.Value[i]) { return false } } return true case *json.Bool: b, ok := b.(*json.Bool) if !ok { return false } return x.Value == b.Value case *json.Number: switch b := b.(type) { case *json.Number: return x.Value == b.Value // XXX: comparing floating point numbers. case *json.Integer: return x.Value == float64(b.Value) // XXX: comparing floating point numbers. default: return false } case *json.Integer: switch b := b.(type) { case *json.Number: return float64(x.Value) == b.Value // XXX: comparing floating point numbers. case *json.Integer: return x.Value == b.Value default: return false } case *json.Null: _, ok := b.(*json.Null) if !ok { return false } return true case *json.Object: b, ok := b.(*json.Object) if !ok { return false } if len(x.Value) != len(b.Value) { return false } for i, item := range x.Value { if !equal(item, b.Find(i.Value)) { return false } } return true case *json.String: b, ok := b.(*json.String) if !ok { return false } return x.Value == b.Value default: return false } }
func validateDraft04Schema(path string, v json.Value) error { switch v := v.(type) { case *json.Object: s, found := v.Lookup("$ref") if found { return validateURI(path+"/$ref", s) } validators := map[string]func(string, json.Value) error{ "type": validateType, "id": validateURI, "$schema": validateURI, "title": validateString, "description": validateString, "multipleOf": validateMultipleOf, "maximum": validateNumber, "minimum": validateNumber, "exclusiveMaximum": validateBoolean, "exclusiveMinimum": validateBoolean, "minLength": validatePositiveInteger, "maxLength": validatePositiveInteger, "pattern": validatePattern, "additionalItems": validateBoolOrSchema, "items": validateItems, "maxItems": validatePositiveInteger, "minItems": validatePositiveInteger, "uniqueItems": validateBoolean, "maxProperties": validatePositiveInteger, "minProperties": validatePositiveInteger, "required": validateStringArray, "additionalProperties": validateBoolOrSchema, "definitions": validateSchemaCollection, "properties": validateSchemaCollection, "patternProperties": validateSchemaCollection, "dependencies": validateDependencies, "enum": validateEnum, "allOf": validateSchemaArray, "anyOf": validateSchemaArray, "oneOf": validateSchemaArray, "not": validateDraft04Schema, } for prop, validate := range validators { val, found := v.Lookup(prop) if !found { continue } err := validate(path+"/"+prop, val) if err != nil { return err } } _, a := v.Lookup("exclusiveMaximum") _, b := v.Lookup("maximum") if a && !b { return fmt.Errorf("%q: \"exclusiveMaximum\" requires \"maximum\" to be present") } _, a = v.Lookup("exclusiveMinimum") _, b = v.Lookup("minimum") if a && !b { return fmt.Errorf("%q: \"exclusiveMinimum\" requires \"minimum\" to be present") } return nil default: return fmt.Errorf("%q has invalid type, it needs to be an object", path) } }