mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2024-12-13 18:27:10 +01:00
Merge pull request #205 from open-source-parsers/reject-dup-keys
[Shekhar (shakers007) wrote](https://sourceforge.net/p/jsoncpp/bugs/22/): > As per RFC4627 (section 2.2), names within an object should be unique. When using JSONCPP's strict mode, parsing such an object should fail.
This commit is contained in:
commit
b2a7438d08
@ -320,6 +320,8 @@ public:
|
|||||||
- `"failIfExtra": false or true`
|
- `"failIfExtra": false or true`
|
||||||
- If true, `parse()` returns false when extra non-whitespace trails
|
- If true, `parse()` returns false when extra non-whitespace trails
|
||||||
the JSON value in the input string.
|
the JSON value in the input string.
|
||||||
|
- `"rejectDupKeys": false or true`
|
||||||
|
- If true, `parse()` returns false when a key is duplicated within an object.
|
||||||
|
|
||||||
You can examine 'settings_` yourself
|
You can examine 'settings_` yourself
|
||||||
to see the defaults. You can also write and read them just like any
|
to see the defaults. You can also write and read them just like any
|
||||||
|
@ -916,6 +916,7 @@ public:
|
|||||||
bool allowNumericKeys_;
|
bool allowNumericKeys_;
|
||||||
bool allowSingleQuotes_;
|
bool allowSingleQuotes_;
|
||||||
bool failIfExtra_;
|
bool failIfExtra_;
|
||||||
|
bool rejectDupKeys_;
|
||||||
int stackLimit_;
|
int stackLimit_;
|
||||||
}; // OurFeatures
|
}; // OurFeatures
|
||||||
|
|
||||||
@ -1431,6 +1432,11 @@ bool OurReader::readObject(Token& tokenStart) {
|
|||||||
"Missing ':' after object member name", colon, tokenObjectEnd);
|
"Missing ':' after object member name", colon, tokenObjectEnd);
|
||||||
}
|
}
|
||||||
if (name.length() >= (1U<<30)) throw std::runtime_error("keylength >= 2^30");
|
if (name.length() >= (1U<<30)) throw std::runtime_error("keylength >= 2^30");
|
||||||
|
if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
|
||||||
|
std::string msg = "Duplicate key: '" + name + "'";
|
||||||
|
return addErrorAndRecover(
|
||||||
|
msg, tokenName, tokenObjectEnd);
|
||||||
|
}
|
||||||
Value& value = currentValue()[name];
|
Value& value = currentValue()[name];
|
||||||
nodes_.push(&value);
|
nodes_.push(&value);
|
||||||
bool ok = readValue();
|
bool ok = readValue();
|
||||||
@ -1896,6 +1902,7 @@ CharReader* CharReaderBuilder::newCharReader() const
|
|||||||
features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
|
features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
|
||||||
features.stackLimit_ = settings_["stackLimit"].asInt();
|
features.stackLimit_ = settings_["stackLimit"].asInt();
|
||||||
features.failIfExtra_ = settings_["failIfExtra"].asBool();
|
features.failIfExtra_ = settings_["failIfExtra"].asBool();
|
||||||
|
features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
|
||||||
return new OurCharReader(collectComments, features);
|
return new OurCharReader(collectComments, features);
|
||||||
}
|
}
|
||||||
static void getValidReaderKeys(std::set<std::string>* valid_keys)
|
static void getValidReaderKeys(std::set<std::string>* valid_keys)
|
||||||
@ -1909,6 +1916,7 @@ static void getValidReaderKeys(std::set<std::string>* valid_keys)
|
|||||||
valid_keys->insert("allowSingleQuotes");
|
valid_keys->insert("allowSingleQuotes");
|
||||||
valid_keys->insert("stackLimit");
|
valid_keys->insert("stackLimit");
|
||||||
valid_keys->insert("failIfExtra");
|
valid_keys->insert("failIfExtra");
|
||||||
|
valid_keys->insert("rejectDupKeys");
|
||||||
}
|
}
|
||||||
bool CharReaderBuilder::validate(Json::Value* invalid) const
|
bool CharReaderBuilder::validate(Json::Value* invalid) const
|
||||||
{
|
{
|
||||||
@ -1941,6 +1949,7 @@ void CharReaderBuilder::strictMode(Json::Value* settings)
|
|||||||
(*settings)["allowNumericKeys"] = false;
|
(*settings)["allowNumericKeys"] = false;
|
||||||
(*settings)["allowSingleQuotes"] = false;
|
(*settings)["allowSingleQuotes"] = false;
|
||||||
(*settings)["failIfExtra"] = true;
|
(*settings)["failIfExtra"] = true;
|
||||||
|
(*settings)["rejectDupKeys"] = true;
|
||||||
//! [CharReaderBuilderStrictMode]
|
//! [CharReaderBuilderStrictMode]
|
||||||
}
|
}
|
||||||
// static
|
// static
|
||||||
@ -1955,6 +1964,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
|
|||||||
(*settings)["allowSingleQuotes"] = false;
|
(*settings)["allowSingleQuotes"] = false;
|
||||||
(*settings)["stackLimit"] = 1000;
|
(*settings)["stackLimit"] = 1000;
|
||||||
(*settings)["failIfExtra"] = false;
|
(*settings)["failIfExtra"] = false;
|
||||||
|
(*settings)["rejectDupKeys"] = false;
|
||||||
//! [CharReaderBuilderDefaults]
|
//! [CharReaderBuilderDefaults]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1884,6 +1884,29 @@ JSONTEST_FIXTURE(CharReaderTest, parseWithStackLimit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct CharReaderStrictModeTest : JsonTest::TestCase {};
|
||||||
|
|
||||||
|
JSONTEST_FIXTURE(CharReaderStrictModeTest, dupKeys) {
|
||||||
|
Json::CharReaderBuilder b;
|
||||||
|
Json::Value root;
|
||||||
|
char const doc[] =
|
||||||
|
"{ \"property\" : \"value\", \"key\" : \"val1\", \"key\" : \"val2\" }";
|
||||||
|
{
|
||||||
|
b.strictMode(&b.settings_);
|
||||||
|
Json::CharReader* reader(b.newCharReader());
|
||||||
|
std::string errs;
|
||||||
|
bool ok = reader->parse(
|
||||||
|
doc, doc + std::strlen(doc),
|
||||||
|
&root, &errs);
|
||||||
|
JSONTEST_ASSERT(!ok);
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL(
|
||||||
|
"* Line 1, Column 41\n"
|
||||||
|
" Duplicate key: 'key'\n",
|
||||||
|
errs);
|
||||||
|
JSONTEST_ASSERT_EQUAL("val1", root["key"]); // so far
|
||||||
|
delete reader;
|
||||||
|
}
|
||||||
|
}
|
||||||
struct CharReaderFailIfExtraTest : JsonTest::TestCase {};
|
struct CharReaderFailIfExtraTest : JsonTest::TestCase {};
|
||||||
|
|
||||||
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) {
|
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) {
|
||||||
@ -2305,6 +2328,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithDetailError);
|
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithDetailError);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithStackLimit);
|
JSONTEST_REGISTER_FIXTURE(runner, CharReaderTest, parseWithStackLimit);
|
||||||
|
|
||||||
|
JSONTEST_REGISTER_FIXTURE(runner, CharReaderStrictModeTest, dupKeys);
|
||||||
|
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue164);
|
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue164);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue107);
|
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, issue107);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, commentAfterObject);
|
JSONTEST_REGISTER_FIXTURE(runner, CharReaderFailIfExtraTest, commentAfterObject);
|
||||||
|
Loading…
Reference in New Issue
Block a user