Skip to content

Commit 7d1f656

Browse files
committed
Merge pull request open-source-parsers#183 from open-source-parsers/allow-single-quote
Allow single quote
2 parents f9db82a + 0c66e69 commit 7d1f656

File tree

3 files changed

+67
-14
lines changed

3 files changed

+67
-14
lines changed

include/json/reader.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,8 @@ class JSON_API CharReaderBuilder : public CharReader::Factory {
310310
- true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
311311
- `"allowNumericKeys": false or true`
312312
- true if numeric object keys are allowed.
313+
- `"allowSingleQuotes": false or true`
314+
- true if '' are allowed for strings (both keys and values)
313315
- `"stackLimit": integer`
314316
- Exceeding stackLimit (recursive depth of `readValue()`) will
315317
cause an exception.

src/lib_json/json_reader.cpp

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -909,12 +909,12 @@ bool Reader::good() const {
909909
class OurFeatures {
910910
public:
911911
static OurFeatures all();
912-
static OurFeatures strictMode();
913912
OurFeatures();
914913
bool allowComments_;
915914
bool strictRoot_;
916915
bool allowDroppedNullPlaceholders_;
917916
bool allowNumericKeys_;
917+
bool allowSingleQuotes_;
918918
bool failIfExtra_;
919919
int stackLimit_;
920920
}; // OurFeatures
@@ -923,20 +923,15 @@ class OurFeatures {
923923
// ////////////////////////////////
924924

925925
OurFeatures::OurFeatures()
926-
: allowComments_(true), strictRoot_(false),
927-
allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
926+
: allowComments_(true), strictRoot_(false)
927+
, allowDroppedNullPlaceholders_(false), allowNumericKeys_(false)
928+
, allowSingleQuotes_(false)
929+
, failIfExtra_(false)
930+
{
931+
}
928932

929933
OurFeatures OurFeatures::all() { return OurFeatures(); }
930934

931-
OurFeatures OurFeatures::strictMode() {
932-
OurFeatures features;
933-
features.allowComments_ = false;
934-
features.strictRoot_ = true;
935-
features.allowDroppedNullPlaceholders_ = false;
936-
features.allowNumericKeys_ = false;
937-
return features;
938-
}
939-
940935
// Implementation of class Reader
941936
// ////////////////////////////////
942937

@@ -1006,6 +1001,7 @@ class OurReader {
10061001
bool readCStyleComment();
10071002
bool readCppStyleComment();
10081003
bool readString();
1004+
bool readStringSingleQuote();
10091005
void readNumber();
10101006
bool readValue();
10111007
bool readObject(Token& token);
@@ -1220,6 +1216,12 @@ bool OurReader::readToken(Token& token) {
12201216
token.type_ = tokenString;
12211217
ok = readString();
12221218
break;
1219+
case '\'':
1220+
if (features_.allowSingleQuotes_) {
1221+
token.type_ = tokenString;
1222+
ok = readStringSingleQuote();
1223+
break;
1224+
} // else continue
12231225
case '/':
12241226
token.type_ = tokenComment;
12251227
ok = readComment();
@@ -1371,7 +1373,6 @@ void OurReader::readNumber() {
13711373
c = (current_ = p) < end_ ? *p++ : 0;
13721374
}
13731375
}
1374-
13751376
bool OurReader::readString() {
13761377
Char c = 0;
13771378
while (current_ != end_) {
@@ -1384,6 +1385,19 @@ bool OurReader::readString() {
13841385
return c == '"';
13851386
}
13861387

1388+
1389+
bool OurReader::readStringSingleQuote() {
1390+
Char c = 0;
1391+
while (current_ != end_) {
1392+
c = getNextChar();
1393+
if (c == '\\')
1394+
getNextChar();
1395+
else if (c == '\'')
1396+
break;
1397+
}
1398+
return c == '\'';
1399+
}
1400+
13871401
bool OurReader::readObject(Token& tokenStart) {
13881402
Token tokenName;
13891403
std::string name;
@@ -1878,6 +1892,7 @@ CharReader* CharReaderBuilder::newCharReader() const
18781892
features.strictRoot_ = settings_["strictRoot"].asBool();
18791893
features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
18801894
features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
1895+
features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
18811896
features.stackLimit_ = settings_["stackLimit"].asInt();
18821897
features.failIfExtra_ = settings_["failIfExtra"].asBool();
18831898
return new OurCharReader(collectComments, features);
@@ -1890,6 +1905,7 @@ static void getValidReaderKeys(std::set<std::string>* valid_keys)
18901905
valid_keys->insert("strictRoot");
18911906
valid_keys->insert("allowDroppedNullPlaceholders");
18921907
valid_keys->insert("allowNumericKeys");
1908+
valid_keys->insert("allowSingleQuotes");
18931909
valid_keys->insert("stackLimit");
18941910
valid_keys->insert("failIfExtra");
18951911
}
@@ -1919,6 +1935,7 @@ void CharReaderBuilder::strictMode(Json::Value* settings)
19191935
(*settings)["strictRoot"] = true;
19201936
(*settings)["allowDroppedNullPlaceholders"] = false;
19211937
(*settings)["allowNumericKeys"] = false;
1938+
(*settings)["allowSingleQuotes"] = false;
19221939
(*settings)["failIfExtra"] = true;
19231940
//! [CharReaderBuilderStrictMode]
19241941
}
@@ -1931,6 +1948,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
19311948
(*settings)["strictRoot"] = false;
19321949
(*settings)["allowDroppedNullPlaceholders"] = false;
19331950
(*settings)["allowNumericKeys"] = false;
1951+
(*settings)["allowSingleQuotes"] = false;
19341952
(*settings)["stackLimit"] = 1000;
19351953
(*settings)["failIfExtra"] = false;
19361954
//! [CharReaderBuilderDefaults]

src/test_lib_json/main.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1861,7 +1861,6 @@ JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterBool) {
18611861
JSONTEST_ASSERT_EQUAL(true, root.asBool());
18621862
delete reader;
18631863
}
1864-
18651864
struct CharReaderAllowDropNullTest : JsonTest::TestCase {};
18661865

18671866
JSONTEST_FIXTURE(CharReaderAllowDropNullTest, issue178) {
@@ -2014,6 +2013,38 @@ JSONTEST_FIXTURE(CharReaderAllowDropNullTest, issue178) {
20142013
delete reader;
20152014
}
20162015

2016+
struct CharReaderAllowSingleQuotesTest : JsonTest::TestCase {};
2017+
2018+
JSONTEST_FIXTURE(CharReaderAllowSingleQuotesTest, issue182) {
2019+
Json::CharReaderBuilder b;
2020+
b.settings_["allowSingleQuotes"] = true;
2021+
Json::Value root;
2022+
std::string errs;
2023+
Json::CharReader* reader(b.newCharReader());
2024+
{
2025+
char const doc[] = "{'a':true,\"b\":true}";
2026+
bool ok = reader->parse(
2027+
doc, doc + std::strlen(doc),
2028+
&root, &errs);
2029+
JSONTEST_ASSERT(ok);
2030+
JSONTEST_ASSERT_STRING_EQUAL("", errs);
2031+
JSONTEST_ASSERT_EQUAL(2u, root.size());
2032+
JSONTEST_ASSERT_EQUAL(true, root.get("a", false));
2033+
JSONTEST_ASSERT_EQUAL(true, root.get("b", false));
2034+
}
2035+
{
2036+
char const doc[] = "{'a': 'x', \"b\":'y'}";
2037+
bool ok = reader->parse(
2038+
doc, doc + std::strlen(doc),
2039+
&root, &errs);
2040+
JSONTEST_ASSERT(ok);
2041+
JSONTEST_ASSERT_STRING_EQUAL("", errs);
2042+
JSONTEST_ASSERT_EQUAL(2u, root.size());
2043+
JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
2044+
JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
2045+
}
2046+
}
2047+
20172048
struct IteratorTest : JsonTest::TestCase {};
20182049

20192050
JSONTEST_FIXTURE(IteratorTest, distance) {
@@ -2079,6 +2110,8 @@ int main(int argc, const char* argv[]) {
20792110

20802111
JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowDropNullTest, issue178);
20812112

2113+
JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowSingleQuotesTest, issue182);
2114+
20822115
JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, distance);
20832116

20842117
return runner.runCommandLine(argc, argv);

0 commit comments

Comments
 (0)