Implement Multi-type
This commit is contained in:
parent
e0c26e44c0
commit
0713b8931d
@ -26,17 +26,31 @@ RAPIDJSON_DIAG_OFF(float-equal)
|
|||||||
|
|
||||||
RAPIDJSON_NAMESPACE_BEGIN
|
RAPIDJSON_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
enum SchemaType {
|
||||||
|
kNullSchemaType,
|
||||||
|
kBooleanSchemaType,
|
||||||
|
kObjectSchemaType,
|
||||||
|
kArraySchemaType,
|
||||||
|
kStringSchemaType,
|
||||||
|
kNumberSchemaType,
|
||||||
|
kIntegerSchemaType,
|
||||||
|
kTotalBasicSchemaType,
|
||||||
|
kTypelessSchemaType = kTotalBasicSchemaType,
|
||||||
|
kMultiTypeSchemaType,
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
class BaseSchema;
|
class BaseSchema;
|
||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
struct SchemaValidationContext {
|
struct SchemaValidationContext {
|
||||||
SchemaValidationContext(const BaseSchema<Encoding>* s) : schema(s), valueSchema() {}
|
SchemaValidationContext(const BaseSchema<Encoding>* s) : schema(s), valueSchema(), multiTypeSchema() {}
|
||||||
|
|
||||||
~SchemaValidationContext() {}
|
~SchemaValidationContext() {}
|
||||||
|
|
||||||
const BaseSchema<Encoding>* schema;
|
const BaseSchema<Encoding>* schema;
|
||||||
const BaseSchema<Encoding>* valueSchema;
|
const BaseSchema<Encoding>* valueSchema;
|
||||||
|
const BaseSchema<Encoding>* multiTypeSchema;
|
||||||
SizeType objectRequiredCount;
|
SizeType objectRequiredCount;
|
||||||
SizeType arrayElementIndex;
|
SizeType arrayElementIndex;
|
||||||
};
|
};
|
||||||
@ -50,8 +64,7 @@ public:
|
|||||||
BaseSchema() {}
|
BaseSchema() {}
|
||||||
|
|
||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
BaseSchema(const ValueType& value)
|
BaseSchema(const ValueType& value) {
|
||||||
{
|
|
||||||
typename ValueType::ConstMemberIterator enumItr = value.FindMember("enum");
|
typename ValueType::ConstMemberIterator enumItr = value.FindMember("enum");
|
||||||
if (enumItr != value.MemberEnd()) {
|
if (enumItr != value.MemberEnd()) {
|
||||||
if (enumItr->value.IsArray() && enumItr->value.Size() > 0)
|
if (enumItr->value.IsArray() && enumItr->value.Size() > 0)
|
||||||
@ -64,6 +77,9 @@ public:
|
|||||||
|
|
||||||
virtual ~BaseSchema() {}
|
virtual ~BaseSchema() {}
|
||||||
|
|
||||||
|
virtual SchemaType GetSchemaType() const = 0;
|
||||||
|
|
||||||
|
virtual bool HandleMultiType(Context&, SchemaType) const { return true; }
|
||||||
virtual bool BeginValue(Context&) const { return true; }
|
virtual bool BeginValue(Context&) const { return true; }
|
||||||
|
|
||||||
virtual bool Null() const { return !enum_.IsArray() || CheckEnum(GenericValue<Encoding>().Move()); }
|
virtual bool Null() const { return !enum_.IsArray() || CheckEnum(GenericValue<Encoding>().Move()); }
|
||||||
@ -92,6 +108,9 @@ protected:
|
|||||||
GenericValue<Encoding> enum_;
|
GenericValue<Encoding> enum_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Encoding, typename ValueType>
|
||||||
|
inline BaseSchema<Encoding>* CreateSchema(const ValueType& value, const ValueType& type);
|
||||||
|
|
||||||
template <typename Encoding, typename ValueType>
|
template <typename Encoding, typename ValueType>
|
||||||
inline BaseSchema<Encoding>* CreateSchema(const ValueType& value);
|
inline BaseSchema<Encoding>* CreateSchema(const ValueType& value);
|
||||||
|
|
||||||
@ -105,9 +124,61 @@ public:
|
|||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
TypelessSchema(const ValueType& value) : BaseSchema<Encoding>(value) {}
|
TypelessSchema(const ValueType& value) : BaseSchema<Encoding>(value) {}
|
||||||
|
|
||||||
|
virtual SchemaType GetSchemaType() const { return kTypelessSchemaType; }
|
||||||
|
|
||||||
virtual bool BeginValue(Context& context) const { context.valueSchema = this; return true; }
|
virtual bool BeginValue(Context& context) const { context.valueSchema = this; return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Encoding>
|
||||||
|
class MultiTypeSchema : public BaseSchema<Encoding> {
|
||||||
|
public:
|
||||||
|
typedef SchemaValidationContext<Encoding> Context;
|
||||||
|
|
||||||
|
template <typename ValueType>
|
||||||
|
MultiTypeSchema(const ValueType& value, const ValueType& type) : BaseSchema<Encoding>(), typedSchemas_() {
|
||||||
|
RAPIDJSON_ASSERT(type.IsArray());
|
||||||
|
for (typename ValueType::ConstValueIterator itr = type.Begin(); itr != type.End(); ++itr) {
|
||||||
|
if (itr->IsString()) {
|
||||||
|
BaseSchema<Encoding>* schema = CreateSchema<Encoding, ValueType>(value, *itr);
|
||||||
|
SchemaType schemaType = schema->GetSchemaType();
|
||||||
|
RAPIDJSON_ASSERT(schemaType < kTotalBasicSchemaType);
|
||||||
|
if (typedSchemas_[schemaType] == 0)
|
||||||
|
typedSchemas_[schemaType] = schema;
|
||||||
|
else {
|
||||||
|
// Erorr: not unique type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~MultiTypeSchema() {
|
||||||
|
for (size_t i = 0; i < kTotalBasicSchemaType; i++)
|
||||||
|
delete typedSchemas_[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual SchemaType GetSchemaType() const { return kMultiTypeSchemaType; };
|
||||||
|
|
||||||
|
virtual bool HandleMultiType(Context& context, SchemaType schemaType) const {
|
||||||
|
RAPIDJSON_ASSERT(schemaType < kTotalBasicSchemaType);
|
||||||
|
if (typedSchemas_[schemaType]) {
|
||||||
|
context.multiTypeSchema = typedSchemas_[schemaType];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (schemaType == kIntegerSchemaType && typedSchemas_[kNumberSchemaType]) {
|
||||||
|
context.multiTypeSchema = typedSchemas_[kNumberSchemaType];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
BaseSchema<Encoding>* typedSchemas_[kTotalBasicSchemaType];
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
class NullSchema : public BaseSchema<Encoding> {
|
class NullSchema : public BaseSchema<Encoding> {
|
||||||
public:
|
public:
|
||||||
@ -117,6 +188,8 @@ public:
|
|||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
NullSchema(const ValueType& value) : BaseSchema<Encoding>(value) {}
|
NullSchema(const ValueType& value) : BaseSchema<Encoding>(value) {}
|
||||||
|
|
||||||
|
virtual SchemaType GetSchemaType() const { return kNullSchemaType; }
|
||||||
|
|
||||||
virtual bool Null() const { return BaseSchema<Encoding>::Null(); }
|
virtual bool Null() const { return BaseSchema<Encoding>::Null(); }
|
||||||
virtual bool Bool(bool) const { return false; }
|
virtual bool Bool(bool) const { return false; }
|
||||||
virtual bool Int(int) const { return false; }
|
virtual bool Int(int) const { return false; }
|
||||||
@ -141,6 +214,8 @@ public:
|
|||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
BooleanSchema(const ValueType& value) : BaseSchema<Encoding>(value) {}
|
BooleanSchema(const ValueType& value) : BaseSchema<Encoding>(value) {}
|
||||||
|
|
||||||
|
virtual SchemaType GetSchemaType() const { return kBooleanSchemaType; }
|
||||||
|
|
||||||
virtual bool Null() const { return false; }
|
virtual bool Null() const { return false; }
|
||||||
virtual bool Bool(bool b) const { return BaseSchema<Encoding>::Bool(b); }
|
virtual bool Bool(bool b) const { return BaseSchema<Encoding>::Bool(b); }
|
||||||
virtual bool Int(int) const { return false; }
|
virtual bool Int(int) const { return false; }
|
||||||
@ -241,6 +316,8 @@ public:
|
|||||||
delete additionalPropertySchema_;
|
delete additionalPropertySchema_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual SchemaType GetSchemaType() const { return kObjectSchemaType; }
|
||||||
|
|
||||||
virtual bool Null() const { return false; }
|
virtual bool Null() const { return false; }
|
||||||
virtual bool Bool(bool) const { return false; }
|
virtual bool Bool(bool) const { return false; }
|
||||||
virtual bool Int(int) const { return false; }
|
virtual bool Int(int) const { return false; }
|
||||||
@ -402,6 +479,8 @@ public:
|
|||||||
delete [] itemsTuple_;
|
delete [] itemsTuple_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual SchemaType GetSchemaType() const { return kArraySchemaType; }
|
||||||
|
|
||||||
virtual bool BeginValue(Context& context) const {
|
virtual bool BeginValue(Context& context) const {
|
||||||
if (itemsList_)
|
if (itemsList_)
|
||||||
context.valueSchema = itemsList_;
|
context.valueSchema = itemsList_;
|
||||||
@ -482,6 +561,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual SchemaType GetSchemaType() const { return kStringSchemaType; }
|
||||||
|
|
||||||
virtual bool Null() const { return false; }
|
virtual bool Null() const { return false; }
|
||||||
virtual bool Bool(bool) const { return false; }
|
virtual bool Bool(bool) const { return false; }
|
||||||
virtual bool Int(int) const { return false; }
|
virtual bool Int(int) const { return false; }
|
||||||
@ -568,6 +649,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual SchemaType GetSchemaType() const { return kIntegerSchemaType; }
|
||||||
|
|
||||||
virtual bool Null() const { return false; }
|
virtual bool Null() const { return false; }
|
||||||
virtual bool Bool(bool) const { return false; }
|
virtual bool Bool(bool) const { return false; }
|
||||||
|
|
||||||
@ -713,6 +796,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual SchemaType GetSchemaType() const { return kNumberSchemaType; }
|
||||||
|
|
||||||
virtual bool Null() const { return false; }
|
virtual bool Null() const { return false; }
|
||||||
virtual bool Bool(bool) const { return false; }
|
virtual bool Bool(bool) const { return false; }
|
||||||
|
|
||||||
@ -745,6 +830,18 @@ private:
|
|||||||
bool exclusiveMaximum_;
|
bool exclusiveMaximum_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Encoding, typename ValueType>
|
||||||
|
inline BaseSchema<Encoding>* CreateSchema(const ValueType& value, const ValueType& type) {
|
||||||
|
if (type == Value("null" ).Move()) return new NullSchema<Encoding>(value);
|
||||||
|
else if (type == Value("boolean").Move()) return new BooleanSchema<Encoding>(value);
|
||||||
|
else if (type == Value("object" ).Move()) return new ObjectSchema<Encoding>(value);
|
||||||
|
else if (type == Value("array" ).Move()) return new ArraySchema<Encoding>(value);
|
||||||
|
else if (type == Value("string" ).Move()) return new StringSchema<Encoding>(value);
|
||||||
|
else if (type == Value("integer").Move()) return new IntegerSchema<Encoding>(value);
|
||||||
|
else if (type == Value("number" ).Move()) return new NumberSchema<Encoding>(value);
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Encoding, typename ValueType>
|
template <typename Encoding, typename ValueType>
|
||||||
inline BaseSchema<Encoding>* CreateSchema(const ValueType& value) {
|
inline BaseSchema<Encoding>* CreateSchema(const ValueType& value) {
|
||||||
if (!value.IsObject())
|
if (!value.IsObject())
|
||||||
@ -752,15 +849,9 @@ inline BaseSchema<Encoding>* CreateSchema(const ValueType& value) {
|
|||||||
|
|
||||||
typename ValueType::ConstMemberIterator typeItr = value.FindMember("type");
|
typename ValueType::ConstMemberIterator typeItr = value.FindMember("type");
|
||||||
|
|
||||||
if (typeItr == value.MemberEnd()) return new TypelessSchema<Encoding>(value);
|
if (typeItr == value.MemberEnd()) return new TypelessSchema<Encoding>(value);
|
||||||
else if (typeItr->value == Value("null" ).Move()) return new NullSchema<Encoding>(value);
|
else if (typeItr->value.IsArray()) return new MultiTypeSchema<Encoding>(value, typeItr->value);
|
||||||
else if (typeItr->value == Value("boolean").Move()) return new BooleanSchema<Encoding>(value);
|
else return CreateSchema<Encoding, ValueType>(value, typeItr->value);
|
||||||
else if (typeItr->value == Value("object" ).Move()) return new ObjectSchema<Encoding>(value);
|
|
||||||
else if (typeItr->value == Value("array" ).Move()) return new ArraySchema<Encoding>(value);
|
|
||||||
else if (typeItr->value == Value("string" ).Move()) return new StringSchema<Encoding>(value);
|
|
||||||
else if (typeItr->value == Value("integer").Move()) return new IntegerSchema<Encoding>(value);
|
|
||||||
else if (typeItr->value == Value("number" ).Move()) return new NumberSchema<Encoding>(value);
|
|
||||||
else return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
|
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
|
||||||
@ -790,10 +881,10 @@ template <typename Encoding, typename OutputHandler = BaseReaderHandler<Encoding
|
|||||||
class GenericSchemaValidator {
|
class GenericSchemaValidator {
|
||||||
public:
|
public:
|
||||||
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
|
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
|
||||||
typedef GenericSchema<Encoding> SchemaType;
|
typedef GenericSchema<Encoding> SchemaT;
|
||||||
|
|
||||||
GenericSchemaValidator(
|
GenericSchemaValidator(
|
||||||
const Schema& schema,
|
const SchemaT& schema,
|
||||||
Allocator* allocator = 0,
|
Allocator* allocator = 0,
|
||||||
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
|
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
|
||||||
size_t documentStackCapacity = kDefaultDocumentStackCapacity)
|
size_t documentStackCapacity = kDefaultDocumentStackCapacity)
|
||||||
@ -807,7 +898,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
GenericSchemaValidator(
|
GenericSchemaValidator(
|
||||||
const Schema& schema,
|
const SchemaT& schema,
|
||||||
OutputHandler& outputHandler,
|
OutputHandler& outputHandler,
|
||||||
Allocator* allocator = 0,
|
Allocator* allocator = 0,
|
||||||
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
|
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
|
||||||
@ -826,43 +917,50 @@ public:
|
|||||||
documentStack_.Clear();
|
documentStack_.Clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Null() { return BeginValue() && CurrentSchema().Null() && EndValue() && outputHandler_.Null(); }
|
bool Null() { return BeginValue(kNullSchemaType) && CurrentSchema().Null() && EndValue() && outputHandler_.Null(); }
|
||||||
bool Bool(bool b) { return BeginValue() && CurrentSchema().Bool(b) && EndValue() && outputHandler_.Bool(b); }
|
bool Bool(bool b) { return BeginValue(kBooleanSchemaType) && CurrentSchema().Bool(b) && EndValue() && outputHandler_.Bool(b); }
|
||||||
bool Int(int i) { return BeginValue() && CurrentSchema().Int(i) && EndValue() && outputHandler_.Int(i); }
|
bool Int(int i) { return BeginValue(kIntegerSchemaType) && CurrentSchema().Int(i) && EndValue() && outputHandler_.Int(i); }
|
||||||
bool Uint(unsigned u) { return BeginValue() && CurrentSchema().Uint(u) && EndValue() && outputHandler_.Uint(u); }
|
bool Uint(unsigned u) { return BeginValue(kIntegerSchemaType) && CurrentSchema().Uint(u) && EndValue() && outputHandler_.Uint(u); }
|
||||||
bool Int64(int64_t i64) { return BeginValue() && CurrentSchema().Int64(i64) && EndValue() && outputHandler_.Int64(i64); }
|
bool Int64(int64_t i64) { return BeginValue(kIntegerSchemaType) && CurrentSchema().Int64(i64) && EndValue() && outputHandler_.Int64(i64); }
|
||||||
bool Uint64(uint64_t u64) { return BeginValue() && CurrentSchema().Uint64(u64) && EndValue() && outputHandler_.Uint64(u64); }
|
bool Uint64(uint64_t u64) { return BeginValue(kIntegerSchemaType) && CurrentSchema().Uint64(u64) && EndValue() && outputHandler_.Uint64(u64); }
|
||||||
bool Double(double d) { return BeginValue() && CurrentSchema().Double(d) && EndValue() && outputHandler_.Double(d); }
|
bool Double(double d) { return BeginValue(kNumberSchemaType) && CurrentSchema().Double(d) && EndValue() && outputHandler_.Double(d); }
|
||||||
bool String(const Ch* str, SizeType length, bool copy) { return BeginValue() && CurrentSchema().String(str, length, copy) && EndValue() && outputHandler_.String(str, length, copy); }
|
bool String(const Ch* str, SizeType length, bool copy) { return BeginValue(kStringSchemaType) && CurrentSchema().String(str, length, copy) && EndValue() && outputHandler_.String(str, length, copy); }
|
||||||
|
|
||||||
bool StartObject() { return BeginValue() && CurrentSchema().StartObject(CurrentContext()) && outputHandler_.StartObject(); }
|
bool StartObject() { return BeginValue(kObjectSchemaType) && CurrentSchema().StartObject(CurrentContext()) && outputHandler_.StartObject(); }
|
||||||
bool Key(const Ch* str, SizeType len, bool copy) { return CurrentSchema().Key(CurrentContext(), str, len, copy) && outputHandler_.Key(str, len, copy); }
|
bool Key(const Ch* str, SizeType len, bool copy) { return CurrentSchema().Key(CurrentContext(), str, len, copy) && outputHandler_.Key(str, len, copy); }
|
||||||
bool EndObject(SizeType memberCount) { return CurrentSchema().EndObject(CurrentContext(), memberCount) && EndValue() && outputHandler_.EndObject(memberCount); }
|
bool EndObject(SizeType memberCount) { return CurrentSchema().EndObject(CurrentContext(), memberCount) && EndValue() && outputHandler_.EndObject(memberCount); }
|
||||||
|
|
||||||
bool StartArray() { return BeginValue() && CurrentSchema().StartArray(CurrentContext()) ? outputHandler_.StartArray() : false; }
|
bool StartArray() { return BeginValue(kArraySchemaType) && CurrentSchema().StartArray(CurrentContext()) ? outputHandler_.StartArray() : false; }
|
||||||
bool EndArray(SizeType elementCount) { return CurrentSchema().EndArray(CurrentContext(), elementCount) && EndValue() && outputHandler_.EndArray(elementCount); }
|
bool EndArray(SizeType elementCount) { return CurrentSchema().EndArray(CurrentContext(), elementCount) && EndValue() && outputHandler_.EndArray(elementCount); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef BaseSchema<Encoding> BaseSchemaType;
|
typedef BaseSchema<Encoding> BaseSchemaType;
|
||||||
typedef typename BaseSchemaType::Context Context;
|
typedef typename BaseSchemaType::Context Context;
|
||||||
|
|
||||||
bool BeginValue() {
|
bool BeginValue(SchemaType schemaType) {
|
||||||
if (schemaStack_.Empty()) {
|
if (schemaStack_.Empty())
|
||||||
PushSchema(*schema_.root_);
|
PushSchema(*schema_.root_);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
if (!CurrentSchema().BeginValue(CurrentContext()))
|
if (!CurrentSchema().BeginValue(CurrentContext()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (CurrentContext().valueSchema)
|
if (CurrentContext().valueSchema)
|
||||||
PushSchema(*CurrentContext().valueSchema);
|
PushSchema(*CurrentContext().valueSchema);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!CurrentSchema().HandleMultiType(CurrentContext(), schemaType))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (CurrentContext().multiTypeSchema)
|
||||||
|
PushSchema(*CurrentContext().multiTypeSchema);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EndValue() {
|
bool EndValue() {
|
||||||
PopSchema();
|
PopSchema();
|
||||||
|
if (!schemaStack_.Empty() && CurrentContext().multiTypeSchema)
|
||||||
|
PopSchema();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -873,7 +971,7 @@ private:
|
|||||||
|
|
||||||
static const size_t kDefaultSchemaStackCapacity = 256;
|
static const size_t kDefaultSchemaStackCapacity = 256;
|
||||||
static const size_t kDefaultDocumentStackCapacity = 256;
|
static const size_t kDefaultDocumentStackCapacity = 256;
|
||||||
const SchemaType& schema_;
|
const SchemaT& schema_;
|
||||||
BaseReaderHandler<Encoding> nullOutputHandler_;
|
BaseReaderHandler<Encoding> nullOutputHandler_;
|
||||||
OutputHandler& outputHandler_;
|
OutputHandler& outputHandler_;
|
||||||
internal::Stack<Allocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *)
|
internal::Stack<Allocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *)
|
||||||
|
@ -21,9 +21,10 @@ using namespace rapidjson;
|
|||||||
|
|
||||||
#define VALIDATE(schema, json, expected) \
|
#define VALIDATE(schema, json, expected) \
|
||||||
{\
|
{\
|
||||||
EXPECT_TRUE(schema.IsValid());\
|
ASSERT_TRUE(schema.IsValid());\
|
||||||
SchemaValidator validator(schema);\
|
SchemaValidator validator(schema);\
|
||||||
Document d;\
|
Document d;\
|
||||||
|
/*printf("\n%s\n", json);*/\
|
||||||
d.Parse(json);\
|
d.Parse(json);\
|
||||||
EXPECT_FALSE(d.HasParseError());\
|
EXPECT_FALSE(d.HasParseError());\
|
||||||
if (expected)\
|
if (expected)\
|
||||||
@ -42,6 +43,16 @@ TEST(SchemaValidator, Typeless) {
|
|||||||
VALIDATE(s, "{ \"an\": [ \"arbitrarily\", \"nested\" ], \"data\": \"structure\" }", true);
|
VALIDATE(s, "{ \"an\": [ \"arbitrarily\", \"nested\" ], \"data\": \"structure\" }", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SchemaValidator, MultiType) {
|
||||||
|
Document sd;
|
||||||
|
sd.Parse("{ \"type\": [\"number\", \"string\"] }");
|
||||||
|
Schema s(sd);
|
||||||
|
|
||||||
|
VALIDATE(s, "42", true);
|
||||||
|
VALIDATE(s, "\"Life, the universe, and everything\"", true);
|
||||||
|
VALIDATE(s, "[\"Life\", \"the universe\", \"and everything\"]", false);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(SchemaValidator, Enum_Typed) {
|
TEST(SchemaValidator, Enum_Typed) {
|
||||||
Document sd;
|
Document sd;
|
||||||
sd.Parse("{ \"type\": \"string\", \"enum\" : [\"red\", \"amber\", \"green\"] }");
|
sd.Parse("{ \"type\": \"string\", \"enum\" : [\"red\", \"amber\", \"green\"] }");
|
||||||
@ -426,6 +437,8 @@ TEST(SchemaValidator, Null) {
|
|||||||
VALIDATE(s, "\"\"", false);
|
VALIDATE(s, "\"\"", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Additional tests
|
||||||
|
|
||||||
TEST(SchemaValidator, ObjectInArray) {
|
TEST(SchemaValidator, ObjectInArray) {
|
||||||
Document sd;
|
Document sd;
|
||||||
sd.Parse("{\"type\":\"array\", \"items\": { \"type\":\"string\" }}");
|
sd.Parse("{\"type\":\"array\", \"items\": { \"type\":\"string\" }}");
|
||||||
@ -434,4 +447,41 @@ TEST(SchemaValidator, ObjectInArray) {
|
|||||||
VALIDATE(s, "[\"a\"]", true);
|
VALIDATE(s, "[\"a\"]", true);
|
||||||
VALIDATE(s, "[1]", false);
|
VALIDATE(s, "[1]", false);
|
||||||
VALIDATE(s, "[{}]", false);
|
VALIDATE(s, "[{}]", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SchemaValidator, MultiTypeInObject) {
|
||||||
|
Document sd;
|
||||||
|
sd.Parse(
|
||||||
|
"{"
|
||||||
|
" \"type\":\"object\","
|
||||||
|
" \"properties\": {"
|
||||||
|
" \"tel\" : {"
|
||||||
|
" \"type\":[\"integer\", \"string\"]"
|
||||||
|
" }"
|
||||||
|
" }"
|
||||||
|
"}");
|
||||||
|
Schema s(sd);
|
||||||
|
|
||||||
|
VALIDATE(s, "{ \"tel\": 999 }", true);
|
||||||
|
VALIDATE(s, "{ \"tel\": \"123-456\" }", true);
|
||||||
|
VALIDATE(s, "{ \"tel\": true }", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SchemaValidator, MultiTypeWithObject) {
|
||||||
|
Document sd;
|
||||||
|
sd.Parse(
|
||||||
|
"{"
|
||||||
|
" \"type\": [\"object\",\"string\"],"
|
||||||
|
" \"properties\": {"
|
||||||
|
" \"tel\" : {"
|
||||||
|
" \"type\": \"integer\""
|
||||||
|
" }"
|
||||||
|
" }"
|
||||||
|
"}");
|
||||||
|
Schema s(sd);
|
||||||
|
|
||||||
|
VALIDATE(s, "\"Hello\"", true);
|
||||||
|
VALIDATE(s, "{ \"tel\": 999 }", true);
|
||||||
|
VALIDATE(s, "{ \"tel\": \"fail\" }", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user