internal ConstraintsViolationException Validate(object o, State state, JsonSchemaRegistory reg) { if (_schema.Ref != null) { if (reg == null) { reg = JsonSchemaRegistory.GetDefault(); } var schema = reg.Resolve(_schema.Ref); if (schema == null) { // TODO: throw new NotSupportedException(); } return(schema.Validate(o, state, reg)); } ConstraintsViolationException ex = null; if (o is INode) { // unwrap INode return(Validate((o as INode).GenericContent, state, reg)); } var kind = Node.KindOfValue(o); if (_schema.Type != null) { if (_schema.Type.GetType().IsArray) { var ts = (string[])_schema.Type; var found = false; foreach (var t in ts) { if (ValidateKind(kind, t)) { found = true; break; } } if (!found) { var actual = kind.ToString(); var expected = String.Join(", ", ts); var msg = state.CreateMessage("Type is not contained(Actual: {0}; Expected: [{1}])", actual, expected); return(new ConstraintsViolationException(msg)); } } else { var t = (string)_schema.Type; if (!ValidateKind(kind, t)) { var actual = kind.ToString(); var expected = t.ToString(); var msg = state.CreateMessage("Type is not matched(Actual: {0}; Expected: {1})", actual, expected); return(new ConstraintsViolationException(msg)); } } } if (_schema.Enum != null) { var oEnum = o; if (o != null && TypeHelper.TypeWrap(o.GetType()).IsEnum&& kind == NodeKind.String) { oEnum = TypeHelper.GetStringEnumNameOf(o); } var found = false; foreach (var e in _schema.Enum) { if (TypeHelper.DeepEquals(oEnum, e)) { found = true; break; } } if (!found) { var msg = state.CreateMessage("Enum is not matched"); return(new ConstraintsViolationException(msg)); } } if (_schema.Not != null) { ex = _schema.Not.Validate(o, state, reg); if (ex == null) { var msg = state.CreateMessage("Not"); return(new ConstraintsViolationException(msg)); } } if (_schema.AllOf != null) { var i = 0; foreach (var jsonSchema in _schema.AllOf) { ex = jsonSchema.Validate(o, state, reg); if (ex != null) { var msg = state.CreateMessage("AllOf[{0}] is failed", i); return(new ConstraintsViolationException(msg, ex)); } ++i; } } if (_schema.AnyOf != null) { var schemaChecked = false; foreach (var jsonSchema in _schema.AnyOf) { ex = jsonSchema.Validate(o, state, reg); if (ex == null) { schemaChecked = true; break; } } if (!schemaChecked) { var msg = state.CreateMessage("None of AnyOf is matched"); return(new ConstraintsViolationException(msg)); } } if (_schema.OneOf != null) { var checkedI = -1; var i = 0; foreach (var jsonSchema in _schema.OneOf) { ex = jsonSchema.Validate(o, state, reg); if (ex == null) { if (checkedI != -1) { var msg = state.CreateMessage("Both of OneOf[{0}] and OneOf[{1}] are matched", checkedI, i); return(new ConstraintsViolationException(msg)); } checkedI = i; } ++i; } if (checkedI == -1) { var msg = state.CreateMessage("None of AnyOf is matched"); return(new ConstraintsViolationException(msg)); } } switch (kind) { case NodeKind.Boolean: break; case NodeKind.Float: case NodeKind.Integer: ex = ValidateNumber(Convert.ToDouble(o), state, reg); if (ex != null) { return(new ConstraintsViolationException("Number", ex)); } break; case NodeKind.String: var oConverted = (o != null && TypeHelper.TypeWrap(o.GetType()).IsEnum) ? TypeHelper.GetStringEnumNameOf(o) : (string)o; ex = ValidateString(oConverted, state, reg); if (ex != null) { return(new ConstraintsViolationException("String", ex)); } break; case NodeKind.Array: ex = ValidateArray(TypeHelper.ToIEnumerable(o), state, reg); if (ex != null) { return(new ConstraintsViolationException("Array", ex)); } break; case NodeKind.Object: ex = ValidateObject(o, state, reg); if (ex != null) { return(new ConstraintsViolationException("Object", ex)); } break; case NodeKind.Null: break; default: throw new NotImplementedException(kind.ToString()); } return(null); }