Code review action items - add comments and consistent error messages for strict mode

This commit is contained in:
Sean Leary
2024-12-21 09:50:52 -06:00
parent d3c7eaf17e
commit 2dcef89a6f
7 changed files with 77 additions and 49 deletions

View File

@@ -67,8 +67,10 @@ public class JSONArray implements Iterable<Object> {
*/
private final ArrayList<Object> myArrayList;
// strict mode checks after constructor require access to this object
private JSONTokener jsonTokener;
// strict mode checks after constructor require access to this object
private JSONParserConfiguration jsonParserConfiguration;
/**
@@ -138,8 +140,16 @@ public class JSONArray implements Iterable<Object> {
throw x.syntaxError("Expected a ',' or ']'");
}
if (nextChar == ']') {
// trailing commas are not allowed in strict mode
if (jsonParserConfiguration.isStrictMode()) {
throw x.syntaxError("Expected another array element");
throw x.syntaxError("Strict mode error: Expected another array element");
}
return;
}
if (nextChar == ',') {
// consecutive commas are not allowed in strict mode
if (jsonParserConfiguration.isStrictMode()) {
throw x.syntaxError("Strict mode error: Expected a valid array element");
}
return;
}
@@ -166,12 +176,10 @@ public class JSONArray implements Iterable<Object> {
*/
public JSONArray(String source) throws JSONException {
this(source, new JSONParserConfiguration());
if (this.jsonParserConfiguration.isStrictMode()) {
char c = jsonTokener.nextClean();
if (c != 0) {
throw jsonTokener.syntaxError(String.format("invalid character '%s' found after end of array", c));
}
// Strict mode does not allow trailing chars
if (this.jsonParserConfiguration.isStrictMode() &&
this.jsonTokener.nextClean() != 0) {
throw jsonTokener.syntaxError("Strict mode error: Unparsed characters found at end of input text");
}
}
@@ -188,12 +196,10 @@ public class JSONArray implements Iterable<Object> {
*/
public JSONArray(String source, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
this(new JSONTokener(source), jsonParserConfiguration);
if (this.jsonParserConfiguration.isStrictMode()) {
char c = jsonTokener.nextClean();
if (c != 0) {
throw jsonTokener.syntaxError(String.format("invalid character '%s' found after end of array", c));
}
// Strict mode does not allow trailing chars
if (this.jsonParserConfiguration.isStrictMode() &&
this.jsonTokener.nextClean() != 0) {
throw jsonTokener.syntaxError("Strict mode error: Unparsed characters found at end of input text");
}
}

View File

@@ -152,8 +152,10 @@ public class JSONObject {
*/
public static final Object NULL = new Null();
// strict mode checks after constructor require access to this object
private JSONTokener jsonTokener;
// strict mode checks after constructor require access to this object
private JSONParserConfiguration jsonParserConfiguration;
/**
@@ -268,13 +270,15 @@ public class JSONObject {
switch (x.nextClean()) {
case ';':
// In strict mode semicolon is not a valid separator
if (jsonParserConfiguration.isStrictMode()) {
throw x.syntaxError("Invalid character ';' found in object in strict mode");
throw x.syntaxError("Strict mode error: Invalid character ';' found");
}
case ',':
if (x.nextClean() == '}') {
// trailing commas are not allowed in strict mode
if (jsonParserConfiguration.isStrictMode()) {
throw x.syntaxError("Expected another object element");
throw x.syntaxError("Strict mode error: Expected another object element");
}
return;
}
@@ -452,9 +456,10 @@ public class JSONObject {
*/
public JSONObject(String source) throws JSONException {
this(source, new JSONParserConfiguration());
// Strict mode does not allow trailing chars
if (this.jsonParserConfiguration.isStrictMode() &&
this.jsonTokener.nextClean() != 0) {
throw new JSONException("Unparsed characters found at end of input text");
throw new JSONException("Strict mode error: Unparsed characters found at end of input text");
}
}
@@ -474,12 +479,10 @@ public class JSONObject {
*/
public JSONObject(String source, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
this(new JSONTokener(source), jsonParserConfiguration);
if (this.jsonParserConfiguration.isStrictMode()) {
char c = jsonTokener.nextClean();
if (c != 0) {
throw jsonTokener.syntaxError(String.format("invalid character '%s' found after end of array", c));
}
// Strict mode does not allow trailing chars
if (this.jsonParserConfiguration.isStrictMode() &&
this.jsonTokener.nextClean() != 0) {
throw new JSONException("Strict mode error: Unparsed characters found at end of input text");
}
}

View File

@@ -64,6 +64,18 @@ public class JSONParserConfiguration extends ParserConfiguration {
return clone;
}
/**
* Sets the strict mode configuration for the JSON parser with default true value
* <p>
* When strict mode is enabled, the parser will throw a JSONException if it encounters an invalid character
* immediately following the final ']' character in the input. This is useful for ensuring strict adherence to the
* JSON syntax, as any characters after the final closing bracket of a JSON array are considered invalid.
* @return a new JSONParserConfiguration instance with the updated strict mode setting
*/
public JSONParserConfiguration withStrictMode() {
return withStrictMode(true);
}
/**
* Sets the strict mode configuration for the JSON parser.
* <p>
@@ -92,13 +104,7 @@ public class JSONParserConfiguration extends ParserConfiguration {
}
/**
* Retrieves the current strict mode setting of the JSON parser.
* <p>
* Strict mode, when enabled, instructs the parser to throw a JSONException if it encounters an invalid character
* immediately following the final ']' character in the input. This ensures strict adherence to the JSON syntax, as
* any characters after the final closing bracket of a JSON array are considered invalid.
*
* @return the current strict mode setting. True if strict mode is enabled, false otherwise.
* @return the current strict mode setting.
*/
public boolean isStrictMode() {
return this.strictMode;

View File

@@ -32,6 +32,7 @@ public class JSONTokener {
/** the number of characters read in the previous line. */
private long characterPreviousLine;
// access to this object is required for strict mode checking
private JSONParserConfiguration jsonParserConfiguration;
/**
@@ -443,10 +444,11 @@ public class JSONTokener {
Object nextSimpleValue(char c) {
String string;
// Strict mode only allows strings with explicit double quotes
if (jsonParserConfiguration != null &&
jsonParserConfiguration.isStrictMode() &&
c == '\'') {
throw this.syntaxError("Single quote wrap not allowed in strict mode");
throw this.syntaxError("Strict mode error: Single quoted strings are not allowed");
}
switch (c) {
case '"':
@@ -477,10 +479,11 @@ public class JSONTokener {
throw this.syntaxError("Missing value");
}
Object obj = JSONObject.stringToValue(string);
// Strict mode only allows strings with explicit double quotes
if (jsonParserConfiguration != null &&
jsonParserConfiguration.isStrictMode() &&
obj instanceof String) {
throw this.syntaxError(String.format("Value '%s' is not surrounded by quotes", obj));
throw this.syntaxError(String.format("Strict mode error: Value '%s' is not surrounded by quotes", obj));
}
return obj;
}