[cpp] Json parsing: adding support for parsing nested lists and top level lists (#4338)

* Extended json parsing capability: add support for parsing nested lists and top level lists

* Stylistic conformance with surrounding code + generalized comments

* More code tidy-up for stylistic conformance with surrounding code

* Blank lines

* Reverted changes related to top-level list parsing

* Styling: newline before else

* Taking out ProcessTableFields which is no longer needed as the top level list change was reverted.
This commit is contained in:
Guillaume Giraud 2017-06-08 01:58:19 +02:00 committed by Wouter van Oortmerssen
parent 86b505e412
commit b1740688bf
2 changed files with 38 additions and 9 deletions

View File

@ -857,17 +857,34 @@ void Parser::SerializeStruct(const StructDef &struct_def, const Value &val) {
CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
uoffset_t *ovalue) {
EXPECT('{');
// We allow tables both as JSON object{ .. } with field names
// or vector[..] with all fields in order
const bool is_nested_list = Is('[');
if (is_nested_list) {
NEXT();
} else {
EXPECT('{');
}
size_t fieldn = 0;
for (;;) {
if ((!opts.strict_json || !fieldn) && Is('}')) { NEXT(); break; }
std::string name = attribute_;
if (Is(kTokenStringConstant)) {
NEXT();
if ((!opts.strict_json || !fieldn) && Is(is_nested_list ? ']' : '}')) { NEXT(); break; }
FieldDef *field = nullptr;
std::string name;
if (is_nested_list) {
if (fieldn > struct_def.fields.vec.size()) {
return Error("too many unnamed fields in nested array");
}
field = struct_def.fields.vec[fieldn];
name = field->name;
} else {
EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier);
name = attribute_;
if (Is(kTokenStringConstant)) {
NEXT();
} else {
EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier);
}
field = struct_def.fields.Lookup(name);
}
auto field = struct_def.fields.Lookup(name);
if (!field) {
if (!opts.skip_unexpected_fields_in_json) {
return Error("unknown field: " + name);
@ -876,7 +893,9 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
ECHECK(SkipAnyJsonValue());
}
} else {
EXPECT(':');
if (!is_nested_list) {
EXPECT(':');
}
if (Is(kTokenNull)) {
NEXT(); // Ignore this field.
} else {
@ -897,9 +916,12 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
fieldn++;
}
}
if (Is('}')) { NEXT(); break; }
if (Is(is_nested_list ? ']' : '}')) { NEXT(); break; }
EXPECT(',');
}
if (is_nested_list && fieldn != struct_def.fields.vec.size()) {
return Error("wrong number of unnamed fields in table vector");
}
// Check if all required fields are parsed.
for (auto field_it = struct_def.fields.vec.begin();

View File

@ -1106,6 +1106,13 @@ void ValueTest() {
12335089644688340133ULL);
}
void NestedListTest() {
flatbuffers::Parser parser1;
TEST_EQ(parser1.Parse("struct Test { a:short; b:byte; } table T { F:[Test]; }"
"root_type T;"
"{ F:[ [10,20], [30,40]] }"), true);
}
void EnumStringsTest() {
flatbuffers::Parser parser1;
TEST_EQ(parser1.Parse("enum E:byte { A, B, C } table T { F:[E]; }"