Skip to content

Commit 7915d85

Browse files
Merge branch 'stleary:master' into feature-disable-whitespace-trim
2 parents 4d6de8c + 55b824d commit 7915d85

15 files changed

+393
-30
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ import org.json.JSONObject;
6666
public class Test {
6767
public static void main(String args[]){
6868
JSONObject jo = new JSONObject("{ \"abc\" : \"def\" }");
69-
System.out.println(jo.toString());
69+
System.out.println(jo);
7070
}
7171
}
7272
```

gradlew

100644100755
File mode changed.

pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@
104104
<configuration>
105105
<source>1.8</source>
106106
<target>1.8</target>
107+
<compilerArgs>
108+
<arg>-Xlint:unchecked</arg>
109+
</compilerArgs>
107110
</configuration>
108111
</plugin>
109112
<plugin>

src/main/java/org/json/CookieList.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,19 @@ public static JSONObject toJSONObject(String string) throws JSONException {
4646
* @throws JSONException if a called function fails
4747
*/
4848
public static String toString(JSONObject jo) throws JSONException {
49-
boolean b = false;
49+
boolean isEndOfPair = false;
5050
final StringBuilder sb = new StringBuilder();
5151
// Don't use the new entrySet API to maintain Android support
5252
for (final String key : jo.keySet()) {
5353
final Object value = jo.opt(key);
5454
if (!JSONObject.NULL.equals(value)) {
55-
if (b) {
55+
if (isEndOfPair) {
5656
sb.append(';');
5757
}
5858
sb.append(Cookie.escape(key));
5959
sb.append("=");
6060
sb.append(Cookie.escape(value.toString()));
61-
b = true;
61+
isEndOfPair = true;
6262
}
6363
}
6464
return sb.toString();

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

Lines changed: 99 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,40 @@ public JSONArray(String source) throws JSONException {
149149
* A Collection.
150150
*/
151151
public JSONArray(Collection<?> collection) {
152+
this(collection, 0, new JSONParserConfiguration());
153+
}
154+
155+
/**
156+
* Construct a JSONArray from a Collection.
157+
*
158+
* @param collection
159+
* A Collection.
160+
* @param jsonParserConfiguration
161+
* Configuration object for the JSON parser
162+
*/
163+
public JSONArray(Collection<?> collection, JSONParserConfiguration jsonParserConfiguration) {
164+
this(collection, 0, jsonParserConfiguration);
165+
}
166+
167+
/**
168+
* Construct a JSONArray from a collection with recursion depth.
169+
*
170+
* @param collection
171+
* A Collection.
172+
* @param recursionDepth
173+
* Variable for tracking the count of nested object creations.
174+
* @param jsonParserConfiguration
175+
* Configuration object for the JSON parser
176+
*/
177+
JSONArray(Collection<?> collection, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
178+
if (recursionDepth > jsonParserConfiguration.getMaxNestingDepth()) {
179+
throw new JSONException("JSONArray has reached recursion depth limit of " + jsonParserConfiguration.getMaxNestingDepth());
180+
}
152181
if (collection == null) {
153182
this.myArrayList = new ArrayList<Object>();
154183
} else {
155184
this.myArrayList = new ArrayList<Object>(collection.size());
156-
this.addAll(collection, true);
185+
this.addAll(collection, true, recursionDepth, jsonParserConfiguration);
157186
}
158187
}
159188

@@ -205,7 +234,7 @@ public JSONArray(Object array) throws JSONException {
205234
throw new JSONException(
206235
"JSONArray initial value should be a string or collection or array.");
207236
}
208-
this.addAll(array, true);
237+
this.addAll(array, true, 0);
209238
}
210239

211240
/**
@@ -1330,15 +1359,36 @@ public JSONArray put(int index, long value) throws JSONException {
13301359
* The subscript.
13311360
* @param value
13321361
* The Map value.
1333-
* @return this.
1362+
* @return
1363+
* reference to self
13341364
* @throws JSONException
13351365
* If the index is negative or if the value is an invalid
13361366
* number.
13371367
* @throws NullPointerException
13381368
* If a key in the map is <code>null</code>
13391369
*/
13401370
public JSONArray put(int index, Map<?, ?> value) throws JSONException {
1341-
this.put(index, new JSONObject(value));
1371+
this.put(index, new JSONObject(value, new JSONParserConfiguration()));
1372+
return this;
1373+
}
1374+
1375+
/**
1376+
* Put a value in the JSONArray, where the value will be a JSONObject that
1377+
* is produced from a Map.
1378+
*
1379+
* @param index
1380+
* The subscript
1381+
* @param value
1382+
* The Map value.
1383+
* @param jsonParserConfiguration
1384+
* Configuration object for the JSON parser
1385+
* @return reference to self
1386+
* @throws JSONException
1387+
* If the index is negative or if the value is an invalid
1388+
* number.
1389+
*/
1390+
public JSONArray put(int index, Map<?, ?> value, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
1391+
this.put(index, new JSONObject(value, jsonParserConfiguration));
13421392
return this;
13431393
}
13441394

@@ -1779,13 +1829,14 @@ public boolean isEmpty() {
17791829
* @param wrap
17801830
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
17811831
* {@code false} to add the items directly
1782-
*
1832+
* @param recursionDepth
1833+
* Variable for tracking the count of nested object creations.
17831834
*/
1784-
private void addAll(Collection<?> collection, boolean wrap) {
1835+
private void addAll(Collection<?> collection, boolean wrap, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
17851836
this.myArrayList.ensureCapacity(this.myArrayList.size() + collection.size());
17861837
if (wrap) {
17871838
for (Object o: collection){
1788-
this.put(JSONObject.wrap(o));
1839+
this.put(JSONObject.wrap(o, recursionDepth + 1, jsonParserConfiguration));
17891840
}
17901841
} else {
17911842
for (Object o: collection){
@@ -1814,30 +1865,66 @@ private void addAll(Iterable<?> iter, boolean wrap) {
18141865
}
18151866
}
18161867
}
1817-
1868+
18181869
/**
18191870
* Add an array's elements to the JSONArray.
18201871
*
18211872
* @param array
1873+
* Array. If the parameter passed is null, or not an array,
1874+
* JSONArray, Collection, or Iterable, an exception will be
1875+
* thrown.
1876+
* @param wrap
1877+
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
1878+
* {@code false} to add the items directly
1879+
* @throws JSONException
1880+
* If not an array or if an array value is non-finite number.
1881+
*/
1882+
private void addAll(Object array, boolean wrap) throws JSONException {
1883+
this.addAll(array, wrap, 0);
1884+
}
1885+
1886+
/**
1887+
* Add an array's elements to the JSONArray.
1888+
*
1889+
* @param array
1890+
* Array. If the parameter passed is null, or not an array,
1891+
* JSONArray, Collection, or Iterable, an exception will be
1892+
* thrown.
1893+
* @param wrap
1894+
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
1895+
* {@code false} to add the items directly
1896+
* @param recursionDepth
1897+
* Variable for tracking the count of nested object creations.
1898+
*/
1899+
private void addAll(Object array, boolean wrap, int recursionDepth) {
1900+
addAll(array, wrap, recursionDepth, new JSONParserConfiguration());
1901+
}
1902+
/**
1903+
* Add an array's elements to the JSONArray.
1904+
*`
1905+
* @param array
18221906
* Array. If the parameter passed is null, or not an array,
18231907
* JSONArray, Collection, or Iterable, an exception will be
18241908
* thrown.
18251909
* @param wrap
18261910
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
18271911
* {@code false} to add the items directly
1828-
*
1912+
* @param recursionDepth
1913+
* Variable for tracking the count of nested object creations.
1914+
* @param jsonParserConfiguration
1915+
* Variable to pass parser custom configuration for json parsing.
18291916
* @throws JSONException
18301917
* If not an array or if an array value is non-finite number.
18311918
* @throws NullPointerException
18321919
* Thrown if the array parameter is null.
18331920
*/
1834-
private void addAll(Object array, boolean wrap) throws JSONException {
1921+
private void addAll(Object array, boolean wrap, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
18351922
if (array.getClass().isArray()) {
18361923
int length = Array.getLength(array);
18371924
this.myArrayList.ensureCapacity(this.myArrayList.size() + length);
18381925
if (wrap) {
18391926
for (int i = 0; i < length; i += 1) {
1840-
this.put(JSONObject.wrap(Array.get(array, i)));
1927+
this.put(JSONObject.wrap(Array.get(array, i), recursionDepth + 1, jsonParserConfiguration));
18411928
}
18421929
} else {
18431930
for (int i = 0; i < length; i += 1) {
@@ -1850,7 +1937,7 @@ private void addAll(Object array, boolean wrap) throws JSONException {
18501937
// JSONArray
18511938
this.myArrayList.addAll(((JSONArray)array).myArrayList);
18521939
} else if (array instanceof Collection) {
1853-
this.addAll((Collection<?>)array, wrap);
1940+
this.addAll((Collection<?>)array, wrap, recursionDepth);
18541941
} else if (array instanceof Iterable) {
18551942
this.addAll((Iterable<?>)array, wrap);
18561943
} else {

src/main/java/org/json/JSONMLParserConfiguration.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,13 @@ protected JSONMLParserConfiguration clone() {
5555
);
5656
}
5757

58+
@SuppressWarnings("unchecked")
5859
@Override
5960
public JSONMLParserConfiguration withKeepStrings(final boolean newVal) {
6061
return super.withKeepStrings(newVal);
6162
}
6263

64+
@SuppressWarnings("unchecked")
6365
@Override
6466
public JSONMLParserConfiguration withMaxNestingDepth(int maxNestingDepth) {
6567
return super.withMaxNestingDepth(maxNestingDepth);

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

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,30 @@ public JSONObject(JSONTokener x) throws JSONException {
276276
* If a key in the map is <code>null</code>
277277
*/
278278
public JSONObject(Map<?, ?> m) {
279+
this(m, 0, new JSONParserConfiguration());
280+
}
281+
282+
/**
283+
* Construct a JSONObject from a Map with custom json parse configurations.
284+
*
285+
* @param m
286+
* A map object that can be used to initialize the contents of
287+
* the JSONObject.
288+
* @param jsonParserConfiguration
289+
* Variable to pass parser custom configuration for json parsing.
290+
*/
291+
public JSONObject(Map<?, ?> m, JSONParserConfiguration jsonParserConfiguration) {
292+
this(m, 0, jsonParserConfiguration);
293+
}
294+
295+
/**
296+
* Construct a JSONObject from a map with recursion depth.
297+
*
298+
*/
299+
private JSONObject(Map<?, ?> m, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
300+
if (recursionDepth > jsonParserConfiguration.getMaxNestingDepth()) {
301+
throw new JSONException("JSONObject has reached recursion depth limit of " + jsonParserConfiguration.getMaxNestingDepth());
302+
}
279303
if (m == null) {
280304
this.map = new HashMap<String, Object>();
281305
} else {
@@ -287,7 +311,7 @@ public JSONObject(Map<?, ?> m) {
287311
final Object value = e.getValue();
288312
if (value != null) {
289313
testValidity(value);
290-
this.map.put(String.valueOf(e.getKey()), wrap(value));
314+
this.map.put(String.valueOf(e.getKey()), wrap(value, recursionDepth + 1, jsonParserConfiguration));
291315
}
292316
}
293317
}
@@ -1841,6 +1865,10 @@ private static <A extends Annotation> A getAnnotation(final Method m, final Clas
18411865
}
18421866
}
18431867

1868+
//If the superclass is Object, no annotations will be found any more
1869+
if (c.getSuperclass().equals(Object.class))
1870+
return null;
1871+
18441872
try {
18451873
return getAnnotation(
18461874
c.getSuperclass().getMethod(m.getName(), m.getParameterTypes()),
@@ -1895,6 +1923,10 @@ private static int getAnnotationDepth(final Method m, final Class<? extends Anno
18951923
}
18961924
}
18971925

1926+
//If the superclass is Object, no annotations will be found any more
1927+
if (c.getSuperclass().equals(Object.class))
1928+
return -1;
1929+
18981930
try {
18991931
int d = getAnnotationDepth(
19001932
c.getSuperclass().getMethod(m.getName(), m.getParameterTypes()),
@@ -2566,7 +2598,31 @@ public static Object wrap(Object object) {
25662598
return wrap(object, null);
25672599
}
25682600

2601+
/**
2602+
* Wrap an object, if necessary. If the object is <code>null</code>, return the NULL
2603+
* object. If it is an array or collection, wrap it in a JSONArray. If it is
2604+
* a map, wrap it in a JSONObject. If it is a standard property (Double,
2605+
* String, et al) then it is already wrapped. Otherwise, if it comes from
2606+
* one of the java packages, turn it into a string. And if it doesn't, try
2607+
* to wrap it in a JSONObject. If the wrapping fails, then null is returned.
2608+
*
2609+
* @param object
2610+
* The object to wrap
2611+
* @param recursionDepth
2612+
* Variable for tracking the count of nested object creations.
2613+
* @param jsonParserConfiguration
2614+
* Variable to pass parser custom configuration for json parsing.
2615+
* @return The wrapped value
2616+
*/
2617+
static Object wrap(Object object, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
2618+
return wrap(object, null, recursionDepth, jsonParserConfiguration);
2619+
}
2620+
25692621
private static Object wrap(Object object, Set<Object> objectsRecord) {
2622+
return wrap(object, objectsRecord, 0, new JSONParserConfiguration());
2623+
}
2624+
2625+
private static Object wrap(Object object, Set<Object> objectsRecord, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
25702626
try {
25712627
if (NULL.equals(object)) {
25722628
return NULL;
@@ -2584,14 +2640,14 @@ private static Object wrap(Object object, Set<Object> objectsRecord) {
25842640

25852641
if (object instanceof Collection) {
25862642
Collection<?> coll = (Collection<?>) object;
2587-
return new JSONArray(coll);
2643+
return new JSONArray(coll, recursionDepth, jsonParserConfiguration);
25882644
}
25892645
if (object.getClass().isArray()) {
25902646
return new JSONArray(object);
25912647
}
25922648
if (object instanceof Map) {
25932649
Map<?, ?> map = (Map<?, ?>) object;
2594-
return new JSONObject(map);
2650+
return new JSONObject(map, recursionDepth, jsonParserConfiguration);
25952651
}
25962652
Package objectPackage = object.getClass().getPackage();
25972653
String objectPackageName = objectPackage != null ? objectPackage
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.json;
2+
3+
/**
4+
* Configuration object for the JSON parser. The configuration is immutable.
5+
*/
6+
public class JSONParserConfiguration extends ParserConfiguration {
7+
8+
/**
9+
* Configuration with the default values.
10+
*/
11+
public JSONParserConfiguration() {
12+
super();
13+
}
14+
15+
@Override
16+
protected JSONParserConfiguration clone() {
17+
return new JSONParserConfiguration();
18+
}
19+
20+
@SuppressWarnings("unchecked")
21+
@Override
22+
public JSONParserConfiguration withMaxNestingDepth(final int maxNestingDepth) {
23+
return super.withMaxNestingDepth(maxNestingDepth);
24+
}
25+
26+
}

0 commit comments

Comments
 (0)