mirror of
https://github.com/Tencent/rapidjson.git
synced 2025-03-06 13:41:35 +01:00
Added optional support for trailing commas
This adds kParseTrailingCommasFlag to allow a trailing comma at the end of maps and arrays. This is part of issue #36, adding optional support for relaxed JSON syntax.
This commit is contained in:
parent
ca07fe2fef
commit
3e21bb429d
@ -116,6 +116,7 @@ Parse flags | Meaning
|
||||
`kParseStopWhenDoneFlag` | After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate `kParseErrorDocumentRootNotSingular` error. Using this flag for parsing multiple JSONs in the same stream.
|
||||
`kParseFullPrecisionFlag` | Parse number in full precision (slower). If this flag is not set, the normal precision (faster) is used. Normal precision has maximum 3 [ULP](http://en.wikipedia.org/wiki/Unit_in_the_last_place) error.
|
||||
`kParseCommentsFlag` | Allow one-line `// ...` and multi-line `/* ... */` comments (relaxed JSON syntax).
|
||||
`kParseTrailingCommasFlag` | Allow trailing commas at the end of objects and arrays (relaxed JSON syntax).
|
||||
|
||||
By using a non-type template parameter, instead of a function parameter, C++ compiler can generate code which is optimized for specified combinations, improving speed, and reducing code size (if only using a single specialization). The downside is the flags needed to be determined in compile-time.
|
||||
|
||||
|
@ -149,6 +149,7 @@ enum ParseFlag {
|
||||
kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower).
|
||||
kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments.
|
||||
kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings.
|
||||
kParseTrailingCommasFlag = 128, //!< Allow trailing commas at the end of objects and arrays.
|
||||
kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
|
||||
};
|
||||
|
||||
@ -636,6 +637,15 @@ private:
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
|
||||
break;
|
||||
}
|
||||
|
||||
if (parseFlags & kParseTrailingCommasFlag) {
|
||||
if (is.Peek() == '}') {
|
||||
is.Take();
|
||||
if (RAPIDJSON_UNLIKELY(!handler.EndObject(memberCount)))
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -676,6 +686,15 @@ private:
|
||||
}
|
||||
else
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
|
||||
|
||||
if (parseFlags & kParseTrailingCommasFlag) {
|
||||
if (is.Peek() == ']') {
|
||||
is.Take();
|
||||
if (RAPIDJSON_UNLIKELY(!handler.EndArray(elementCount)))
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -778,6 +778,10 @@ TEST(Reader, ParseArray_Error) {
|
||||
TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1}", 2);
|
||||
TEST_ARRAY_ERROR(kParseErrorArrayMissCommaOrSquareBracket, "[1 2]", 3);
|
||||
|
||||
// Array cannot have a trailing comma (without kParseTrailingCommasFlag);
|
||||
// a value must follow a comma
|
||||
TEST_ARRAY_ERROR(kParseErrorValueInvalid, "[1,]", 3);
|
||||
|
||||
#undef TEST_ARRAY_ERROR
|
||||
}
|
||||
|
||||
@ -978,6 +982,10 @@ TEST(Reader, ParseObject_Error) {
|
||||
// Must be a comma or '}' after an object member
|
||||
TEST_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, "{\"a\":1]", 6);
|
||||
|
||||
// Object cannot have a trailing comma (without kParseTrailingCommasFlag);
|
||||
// an object member name must follow a comma
|
||||
TEST_ERROR(kParseErrorObjectMissName, "{\"a\":1,}", 7);
|
||||
|
||||
// This tests that MemoryStream is checking the length in Peek().
|
||||
{
|
||||
MemoryStream ms("{\"a\"", 1);
|
||||
@ -1552,6 +1560,35 @@ TEST(Reader, NumbersAsStrings) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Reader, TrailingCommas) {
|
||||
{
|
||||
// trailing array comma
|
||||
StringStream s("[1,2,3,]");
|
||||
ParseArrayHandler<3> h;
|
||||
Reader reader;
|
||||
EXPECT_TRUE(reader.Parse<kParseTrailingCommasFlag>(s, h));
|
||||
EXPECT_EQ(5u, h.step_);
|
||||
}
|
||||
{
|
||||
// trailing object comma
|
||||
const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3],}";
|
||||
StringStream s(json);
|
||||
ParseObjectHandler h;
|
||||
Reader reader;
|
||||
EXPECT_TRUE(reader.Parse<kParseTrailingCommasFlag>(s, h));
|
||||
EXPECT_EQ(20u, h.step_);
|
||||
}
|
||||
{
|
||||
// trailing object and array commas with whitespace
|
||||
const char* json = "{ \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3\n,\n]\n,\n } ";
|
||||
StringStream s(json);
|
||||
ParseObjectHandler h;
|
||||
Reader reader;
|
||||
EXPECT_TRUE(reader.Parse<kParseTrailingCommasFlag>(s, h));
|
||||
EXPECT_EQ(20u, h.step_);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user