Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StrictMode Implementation for JSONArray #877

Merged
merged 19 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
dcbbccc
feat(#871-strictMode): strictMode configuration add to JSONParserConf…
rikkarth Mar 15, 2024
63e8314
feat(#871-strictMode): strictMode JSONArray initial implementation
rikkarth Mar 15, 2024
c140e91
test(#871-strictMode): strict mode false initial implementation
rikkarth Mar 15, 2024
e67abb3
feat(#871-strictMode): improved validation, strict mode for quotes im…
rikkarth Mar 15, 2024
c51efe8
docs(#871-strictMode): JSONArray constructor JavaDoc update
rikkarth Mar 15, 2024
0ff368c
chore(#871-strictMode): corrected small syntax typo in unit test
rikkarth Mar 15, 2024
e2fe14d
fix(#871-strictMode): replaced stream with conventional loop for 1.6 …
rikkarth Mar 16, 2024
f3b3491
chore(#871-strictMode): reverted refactor in JSONTokener
rikkarth Mar 16, 2024
3672b5e
chore(#871-strictMode): reverted unrelated changes
rikkarth Mar 17, 2024
8f66865
Merge branch 'master' into feat/871-strictMode
rikkarth Mar 21, 2024
d335447
test(#871-strictMode): add two more test which validate error correct…
rikkarth Mar 22, 2024
49de922
chore(#871-strictMode): fix small spacing typo
rikkarth Mar 22, 2024
372f5ca
feat(#871-strictMode): enhanced and simplified strictMode logic
rikkarth Mar 30, 2024
4929fc9
test(#871-strictMode): added more test cases, improved existing ones
rikkarth Mar 30, 2024
d2cb38d
feat(#871-strictMode): added ORIGINAL implementation to JSONParserCon…
rikkarth Mar 30, 2024
c0918c2
feat(#871-strictMode): add allowSingleQuote option, add enhancements …
rikkarth Mar 30, 2024
46534b5
feat(#871-strictMode): removed allowSingleQuotes
rikkarth Mar 30, 2024
d92d62a
Merge branch 'master' into feat/871-strictMode
rikkarth Mar 30, 2024
3200275
change(stleary#871-strictMode): cleanup
rikkarth Apr 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 85 additions & 54 deletions src/main/java/org/json/JSONArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,31 @@ public JSONArray() {
}

/**
* Construct a JSONArray from a JSONTokener.
* Constructs a JSONArray from a JSONTokener.
* <p>
* This constructor reads the JSONTokener to parse a JSON array. It uses the default JSONParserConfiguration.
*
* @param x
* A JSONTokener
* @throws JSONException
* If there is a syntax error.
* @param x A JSONTokener
* @throws JSONException If there is a syntax error.
*/
public JSONArray(JSONTokener x) throws JSONException {
this(x, new JSONParserConfiguration());
}

/**
* Constructs a JSONArray from a JSONTokener and a JSONParserConfiguration.
* JSONParserConfiguration contains strictMode turned off (false) by default.
*
* @param x A JSONTokener instance from which the JSONArray is constructed.
* @param jsonParserConfiguration A JSONParserConfiguration instance that controls the behavior of the parser.
* @throws JSONException If a syntax error occurs during the construction of the JSONArray.
*/
public JSONArray(JSONTokener x, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
this();
if (x.nextClean() != '[') {
throw x.syntaxError("A JSONArray text must start with '['");
}

char nextChar = x.nextClean();
if (nextChar == 0) {
// array is unclosed. No ']' found, instead EOF
Expand All @@ -101,27 +113,34 @@ public JSONArray(JSONTokener x) throws JSONException {
this.myArrayList.add(JSONObject.NULL);
} else {
x.back();
this.myArrayList.add(x.nextValue());
this.myArrayList.add(x.nextValue(jsonParserConfiguration));
}
switch (x.nextClean()) {
case 0:
// array is unclosed. No ']' found, instead EOF
throw x.syntaxError("Expected a ',' or ']'");
case ',':
nextChar = x.nextClean();
if (nextChar == 0) {
case 0:
// array is unclosed. No ']' found, instead EOF
throw x.syntaxError("Expected a ',' or ']'");
}
if (nextChar == ']') {
case ',':
nextChar = x.nextClean();
if (nextChar == 0) {
// array is unclosed. No ']' found, instead EOF
throw x.syntaxError("Expected a ',' or ']'");
}
if (nextChar == ']') {
return;
}
x.back();
break;
case ']':
if (jsonParserConfiguration.isStrictMode()) {
nextChar = x.nextClean();
if (nextChar != 0) {
throw x.syntaxError("invalid character found after end of array: " + nextChar);
}
}

return;
}
x.back();
break;
case ']':
return;
default:
throw x.syntaxError("Expected a ',' or ']'");
default:
throw x.syntaxError("Expected a ',' or ']'");
}
}
}
Expand All @@ -138,7 +157,19 @@ public JSONArray(JSONTokener x) throws JSONException {
* If there is a syntax error.
*/
public JSONArray(String source) throws JSONException {
this(new JSONTokener(source));
this(new JSONTokener(source), new JSONParserConfiguration());
}

/**
* Constructs a JSONArray from a source JSON text and a JSONParserConfiguration.
*
* @param source A string that begins with <code>[</code>&nbsp;<small>(left bracket)</small> and
* ends with <code>]</code> &nbsp;<small>(right bracket)</small>.
* @param jsonParserConfiguration A JSONParserConfiguration instance that controls the behavior of the parser.
* @throws JSONException If there is a syntax error.
*/
public JSONArray(String source, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
this(new JSONTokener(source), jsonParserConfiguration);
}

/**
Expand Down Expand Up @@ -367,7 +398,7 @@ public Number getNumber(int index) throws JSONException {

/**
* Get the enum value associated with an index.
*
*
* @param <E>
* Enum Type
* @param clazz
Expand Down Expand Up @@ -555,7 +586,7 @@ public String join(String separator) throws JSONException {
if (len == 0) {
return "";
}

StringBuilder sb = new StringBuilder(
JSONObject.valueToString(this.myArrayList.get(0)));

Expand Down Expand Up @@ -869,7 +900,7 @@ public Integer optIntegerObject(int index, Integer defaultValue) {

/**
* Get the enum value associated with a key.
*
*
* @param <E>
* Enum Type
* @param clazz
Expand All @@ -884,7 +915,7 @@ public <E extends Enum<E>> E optEnum(Class<E> clazz, int index) {

/**
* Get the enum value associated with a key.
*
*
* @param <E>
* Enum Type
* @param clazz
Expand Down Expand Up @@ -917,8 +948,8 @@ public <E extends Enum<E>> E optEnum(Class<E> clazz, int index, E defaultValue)
}

/**
* Get the optional BigInteger value associated with an index. The
* defaultValue is returned if there is no value for the index, or if the
* Get the optional BigInteger value associated with an index. The
* defaultValue is returned if there is no value for the index, or if the
* value is not a number and cannot be converted to a number.
*
* @param index
Expand All @@ -933,8 +964,8 @@ public BigInteger optBigInteger(int index, BigInteger defaultValue) {
}

/**
* Get the optional BigDecimal value associated with an index. The
* defaultValue is returned if there is no value for the index, or if the
* Get the optional BigDecimal value associated with an index. The
* defaultValue is returned if there is no value for the index, or if the
* value is not a number and cannot be converted to a number. If the value
* is float or double, the {@link BigDecimal#BigDecimal(double)}
* constructor will be used. See notes on the constructor for conversion
Expand Down Expand Up @@ -1103,7 +1134,7 @@ public Number optNumber(int index, Number defaultValue) {
if (val instanceof Number){
return (Number) val;
}

if (val instanceof String) {
try {
return JSONObject.stringToNumber((String) val);
Expand Down Expand Up @@ -1180,7 +1211,7 @@ public JSONArray put(Collection<?> value) {
public JSONArray put(double value) throws JSONException {
return this.put(Double.valueOf(value));
}

/**
* Append a float value. This increases the array's length by one.
*
Expand Down Expand Up @@ -1435,19 +1466,19 @@ public JSONArray put(int index, Object value) throws JSONException {
*
* @param collection
* A Collection.
* @return this.
* @return this.
*/
public JSONArray putAll(Collection<?> collection) {
this.addAll(collection, false);
return this;
}

/**
* Put an Iterable's elements in to the JSONArray.
*
* @param iter
* An Iterable.
* @return this.
* @return this.
*/
public JSONArray putAll(Iterable<?> iter) {
this.addAll(iter, false);
Expand All @@ -1459,7 +1490,7 @@ public JSONArray putAll(Iterable<?> iter) {
*
* @param array
* A JSONArray.
* @return this.
* @return this.
*/
public JSONArray putAll(JSONArray array) {
// directly copy the elements from the source array to this one
Expand All @@ -1474,7 +1505,7 @@ public JSONArray putAll(JSONArray array) {
* @param array
* Array. If the parameter passed is null, or not an array or Iterable, an
* exception will be thrown.
* @return this.
* @return this.
*
* @throws JSONException
* If not an array, JSONArray, Iterable or if an value is non-finite number.
Expand All @@ -1485,17 +1516,17 @@ public JSONArray putAll(Object array) throws JSONException {
this.addAll(array, false);
return this;
}

/**
* Creates a JSONPointer using an initialization string and tries to
* Creates a JSONPointer using an initialization string and tries to
* match it to an item within this JSONArray. For example, given a
* JSONArray initialized with this document:
* <pre>
* [
* {"b":"c"}
* ]
* </pre>
* and this JSONPointer string:
* and this JSONPointer string:
* <pre>
* "/0/b"
* </pre>
Expand All @@ -1508,17 +1539,17 @@ public JSONArray putAll(Object array) throws JSONException {
public Object query(String jsonPointer) {
return query(new JSONPointer(jsonPointer));
}

/**
* Uses a user initialized JSONPointer and tries to
* Uses a user initialized JSONPointer and tries to
* match it to an item within this JSONArray. For example, given a
* JSONArray initialized with this document:
* <pre>
* [
* {"b":"c"}
* ]
* </pre>
* and this JSONPointer:
* and this JSONPointer:
* <pre>
* "/0/b"
* </pre>
Expand All @@ -1531,23 +1562,23 @@ public Object query(String jsonPointer) {
public Object query(JSONPointer jsonPointer) {
return jsonPointer.queryFrom(this);
}

/**
* Queries and returns a value from this object using {@code jsonPointer}, or
* returns null if the query fails due to a missing key.
*
*
* @param jsonPointer the string representation of the JSON pointer
* @return the queried value or {@code null}
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
*/
public Object optQuery(String jsonPointer) {
return optQuery(new JSONPointer(jsonPointer));
}

/**
* Queries and returns a value from this object using {@code jsonPointer}, or
* returns null if the query fails due to a missing key.
*
*
* @param jsonPointer The JSON pointer
* @return the queried value or {@code null}
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
Expand Down Expand Up @@ -1667,11 +1698,11 @@ public String toString() {

/**
* Make a pretty-printed JSON text of this JSONArray.
*
*
* <p>If <pre> {@code indentFactor > 0}</pre> and the {@link JSONArray} has only
* one element, then the array will be output on a single line:
* <pre>{@code [1]}</pre>
*
*
* <p>If an array has 2 or more elements, then it will be output across
* multiple lines: <pre>{@code
* [
Expand All @@ -1683,7 +1714,7 @@ public String toString() {
* <p><b>
* Warning: This method assumes that the data structure is acyclical.
* </b>
*
*
* @param indentFactor
* The number of spaces to add to each level of indentation.
* @return a printable, displayable, transmittable representation of the
Expand Down Expand Up @@ -1717,11 +1748,11 @@ public Writer write(Writer writer) throws JSONException {

/**
* Write the contents of the JSONArray as JSON text to a writer.
*
*
* <p>If <pre>{@code indentFactor > 0}</pre> and the {@link JSONArray} has only
* one element, then the array will be output on a single line:
* <pre>{@code [1]}</pre>
*
*
* <p>If an array has 2 or more elements, then it will be output across
* multiple lines: <pre>{@code
* [
Expand Down Expand Up @@ -1947,7 +1978,7 @@ private void addAll(Object array, boolean wrap, int recursionDepth, JSONParserCo
"JSONArray initial value should be a string or collection or array.");
}
}

/**
* Create a new JSONException in a common format for incorrect conversions.
* @param idx index of the item
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/org/json/JSONObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,12 @@ public JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration
for (;;) {
c = x.nextClean();
switch (c) {
case 0:
throw x.syntaxError("A JSONObject text must end with '}'");
case '}':
return;
default:
key = x.nextSimpleValue(c).toString();
case 0:
throw x.syntaxError("A JSONObject text must end with '}'");
case '}':
return;
default:
key = x.nextSimpleValue(c, jsonParserConfiguration).toString();
}

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

Object value = x.nextValue();
Object value = x.nextValue(jsonParserConfiguration);
// Only add value if non-null
if (value != null) {
this.put(key, value);
Expand Down Expand Up @@ -1247,7 +1247,7 @@ public BigDecimal optBigDecimal(String key, BigDecimal defaultValue) {
static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue) {
return objectToBigDecimal(val, defaultValue, true);
}

/**
* @param val value to convert
* @param defaultValue default value to return is the conversion doesn't work or is null.
Expand Down
Loading
Loading