Skip to content

Commit c0918c2

Browse files
author
rikkarth
committed
feat(stleary#871-strictMode): add allowSingleQuote option, add enhancements and simplification
1 parent d2cb38d commit c0918c2

File tree

5 files changed

+58
-30
lines changed

5 files changed

+58
-30
lines changed

src/main/java/org/json/JSONArray.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,7 @@ public JSONArray(JSONTokener x, JSONParserConfiguration jsonParserConfiguration)
113113
this.myArrayList.add(JSONObject.NULL);
114114
} else {
115115
x.back();
116-
if (jsonParserConfiguration.isStrictMode()) {
117-
this.myArrayList.add(x.nextValue(true));
118-
} else {
119-
this.myArrayList.add(x.nextValue());
120-
}
116+
this.myArrayList.add(x.nextValue(jsonParserConfiguration));
121117
}
122118
switch (x.nextClean()) {
123119
case 0:

src/main/java/org/json/JSONObject.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ public JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration
225225
case '}':
226226
return;
227227
default:
228-
key = x.nextSimpleValue(c, jsonParserConfiguration.isStrictMode()).toString();
228+
key = x.nextSimpleValue(c, jsonParserConfiguration).toString();
229229
}
230230

231231
// The key is followed by ':'.
@@ -244,7 +244,7 @@ public JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration
244244
throw x.syntaxError("Duplicate key \"" + key + "\"");
245245
}
246246

247-
Object value = getValue(x, jsonParserConfiguration.isStrictMode());
247+
Object value = x.nextValue(jsonParserConfiguration);
248248
// Only add value if non-null
249249
if (value != null) {
250250
this.put(key, value);
@@ -272,12 +272,6 @@ public JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration
272272
}
273273
}
274274

275-
private Object getValue(JSONTokener x, boolean strictMode) {
276-
if (strictMode) {
277-
return x.nextValue(true);
278-
}
279-
return x.nextValue();
280-
}
281275
/**
282276
* Construct a JSONObject from a Map.
283277
*

src/main/java/org/json/JSONParserConfiguration.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public class JSONParserConfiguration extends ParserConfiguration {
2525
*/
2626
private boolean strictMode;
2727

28+
/**
29+
* Allows Single Quotes when strictMode is true. Has no effect if strictMode is false.
30+
*/
31+
private boolean allowSingleQuotes;
32+
2833
/**
2934
* Configuration with the default values.
3035
*/
@@ -92,6 +97,24 @@ public JSONParserConfiguration withStrictMode(final boolean mode) {
9297
return clone;
9398
}
9499

100+
/**
101+
* Allows single quotes mode configuration for JSON parser when strictMode is on.
102+
* <p>
103+
* If this option is set to true when strict Mode is enabled, the parser will allow single quoted fields.
104+
* <p>
105+
* This option is false by default.
106+
*
107+
* @param mode a boolean value indicating whether single quotes should be allowed or not
108+
* @return a new JSONParserConfiguration instance with the updated strict mode setting
109+
*/
110+
public JSONParserConfiguration allowSingleQuotes(final boolean mode) {
111+
JSONParserConfiguration clone = this.clone();
112+
clone.strictMode = this.strictMode;
113+
clone.allowSingleQuotes = mode;
114+
115+
return clone;
116+
}
117+
95118
/**
96119
* The parser's behavior when meeting duplicate keys, controls whether the parser should
97120
* overwrite duplicate keys or not.
@@ -115,4 +138,14 @@ public boolean isOverwriteDuplicateKey() {
115138
public boolean isStrictMode() {
116139
return this.strictMode;
117140
}
141+
142+
/**
143+
* Retrieves the allow single quotes option.
144+
* <p>
145+
* Allow Single Quotes, when enabled during strict mode, instructs the parser to allow single quoted JSON fields.
146+
* The parser will not throw a JSONException if compliant single quoted fields are found in the JSON structure.
147+
*
148+
* @return the current allow single quotes setting.
149+
*/
150+
public boolean isAllowSingleQuotes() {return this.allowSingleQuotes;}
118151
}

src/main/java/org/json/JSONTokener.java

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -412,48 +412,45 @@ public String nextTo(String delimiters) throws JSONException {
412412
* @throws JSONException If syntax error.
413413
*/
414414
public Object nextValue() throws JSONException {
415-
return nextValue(false);
415+
return nextValue(new JSONParserConfiguration());
416416
}
417417

418418
/**
419419
* Get the next value. The value can be a Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the
420420
* JSONObject.NULL object. The strictMode parameter controls the behavior of the method when parsing the value.
421421
*
422-
* @param strictMode If true, the method will strictly adhere to the JSON syntax, throwing a JSONException for any
423-
* deviations.
422+
* @param jsonParserConfiguration which carries options such as strictMode and allowSingleQuotes, these methods will
423+
* strictly adhere to the JSON syntax, throwing a JSONException for any deviations.
424424
* @return An object.
425425
* @throws JSONException If syntax error.
426426
*/
427-
public Object nextValue(boolean strictMode) throws JSONException {
427+
public Object nextValue(JSONParserConfiguration jsonParserConfiguration) throws JSONException {
428428
char c = this.nextClean();
429429
switch (c) {
430430
case '{':
431431
this.back();
432-
return getJsonObject(strictMode);
432+
return getJsonObject(jsonParserConfiguration);
433433
case '[':
434434
this.back();
435435
return getJsonArray();
436436
default:
437-
return nextSimpleValue(c, strictMode);
437+
return nextSimpleValue(c, jsonParserConfiguration);
438438
}
439439
}
440440

441441
/**
442442
* This method is used to get a JSONObject from the JSONTokener. The strictMode parameter controls the behavior of
443443
* the method when parsing the JSONObject.
444444
*
445-
* @param strictMode If true, the method will strictly adhere to the JSON syntax, throwing a JSONException for any
446-
* deviations.
445+
* @param jsonParserConfiguration which carries options such as strictMode and allowSingleQuotes, these methods will
446+
* strictly adhere to the JSON syntax, throwing a JSONException for any deviations.
447+
* deviations.
447448
* @return A JSONObject which is the next value in the JSONTokener.
448449
* @throws JSONException If the JSONObject or JSONArray depth is too large to process.
449450
*/
450-
private JSONObject getJsonObject(boolean strictMode) {
451+
private JSONObject getJsonObject(JSONParserConfiguration jsonParserConfiguration) {
451452
try {
452-
if (strictMode) {
453-
return new JSONObject(this, new JSONParserConfiguration().withStrictMode(true));
454-
}
455-
456-
return new JSONObject(this);
453+
return new JSONObject(this, jsonParserConfiguration);
457454
} catch (StackOverflowError e) {
458455
throw new JSONException("JSON Array or Object depth too large to process.", e);
459456
}
@@ -473,7 +470,14 @@ private JSONArray getJsonArray() {
473470
}
474471
}
475472

476-
Object nextSimpleValue(char c, boolean strictMode) {
473+
Object nextSimpleValue(char c, JSONParserConfiguration jsonParserConfiguration) {
474+
boolean strictMode = jsonParserConfiguration.isStrictMode();
475+
boolean allowSingleQuotes = jsonParserConfiguration.isAllowSingleQuotes();
476+
477+
if(strictMode && !allowSingleQuotes && c == '\''){
478+
throw this.syntaxError("Single quote wrap not allowed in strict mode");
479+
}
480+
477481
if (c == '"' || c == '\'') {
478482
return this.nextString(c, strictMode);
479483
}

src/test/java/org/json/junit/JSONParserConfigurationTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ public void givenInvalidInputArray_testStrictModeFalse_shouldNotThrowAnyExceptio
118118
}
119119

120120
@Test
121-
public void givenUnbalancedQuotes_testStrictModeTrue_shouldThrowJsonExceptionWtihConcreteErrorDescription() {
121+
public void givenUnbalancedQuotes_testStrictModeTrueAndAllowSingleQuotes_shouldThrowJsonExceptionWtihConcreteErrorDescription() {
122122
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
123-
.withStrictMode(true);
123+
.withStrictMode(true).allowSingleQuotes(true);
124124

125125
String testCaseOne = "[\"abc', \"test\"]";
126126
String testCaseTwo = "['abc\", \"test\"]";
@@ -198,6 +198,7 @@ private List<String> getNonCompliantJSONList() {
198198
return Arrays.asList(
199199
"[1,2];[3,4]",
200200
"[test]",
201+
"[{'testSingleQuote': 'testSingleQuote'}]",
201202
"[1, 2,3]:[4,5]",
202203
"[{test: implied}]",
203204
"[{\"test\": implied}]",

0 commit comments

Comments
 (0)