Skip to content

Commit 057e0c7

Browse files
committed
Merge remote-tracking branch 'origin/master' into AndroidSupport
2 parents 3997a90 + cdf3cf7 commit 057e0c7

File tree

6 files changed

+187
-82
lines changed

6 files changed

+187
-82
lines changed

JSONArray.java

+39-9
Original file line numberDiff line numberDiff line change
@@ -1230,7 +1230,7 @@ public Object optQuery(String jsonPointer) {
12301230
* Queries and returns a value from this object using {@code jsonPointer}, or
12311231
* returns null if the query fails due to a missing key.
12321232
*
1233-
* @param The JSON pointer
1233+
* @param jsonPointer The JSON pointer
12341234
* @return the queried value or {@code null}
12351235
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
12361236
*/
@@ -1323,8 +1323,9 @@ public JSONObject toJSONObject(JSONArray names) throws JSONException {
13231323
* whitespace is added. If it is not possible to produce a syntactically
13241324
* correct JSON text then null will be returned instead. This could occur if
13251325
* the array contains an invalid number.
1326-
* <p>
1326+
* <p><b>
13271327
* Warning: This method assumes that the data structure is acyclical.
1328+
* </b>
13281329
*
13291330
* @return a printable, displayable, transmittable representation of the
13301331
* array.
@@ -1339,9 +1340,24 @@ public String toString() {
13391340
}
13401341

13411342
/**
1342-
* Make a pretty-printed JSON text of this JSONArray. Warning: This method
1343-
* assumes that the data structure is acyclical.
1344-
*
1343+
* Make a pretty-printed JSON text of this JSONArray.
1344+
*
1345+
* <p>If <code>indentFactor > 0</code> and the {@link JSONArray} has only
1346+
* one element, then the array will be output on a single line:
1347+
* <pre>{@code [1]}</pre>
1348+
*
1349+
* <p>If an array has 2 or more elements, then it will be output across
1350+
* multiple lines: <pre>{@code
1351+
* [
1352+
* 1,
1353+
* "value 2",
1354+
* 3
1355+
* ]
1356+
* }</pre>
1357+
* <p><b>
1358+
* Warning: This method assumes that the data structure is acyclical.
1359+
* </b>
1360+
*
13451361
* @param indentFactor
13461362
* The number of spaces to add to each level of indentation.
13471363
* @return a printable, displayable, transmittable representation of the
@@ -1360,8 +1376,9 @@ public String toString(int indentFactor) throws JSONException {
13601376
/**
13611377
* Write the contents of the JSONArray as JSON text to a writer. For
13621378
* compactness, no whitespace is added.
1363-
* <p>
1379+
* <p><b>
13641380
* Warning: This method assumes that the data structure is acyclical.
1381+
*</b>
13651382
*
13661383
* @return The writer.
13671384
* @throws JSONException
@@ -1371,10 +1388,23 @@ public Writer write(Writer writer) throws JSONException {
13711388
}
13721389

13731390
/**
1374-
* Write the contents of the JSONArray as JSON text to a writer. For
1375-
* compactness, no whitespace is added.
1376-
* <p>
1391+
* Write the contents of the JSONArray as JSON text to a writer.
1392+
*
1393+
* <p>If <code>indentFactor > 0</code> and the {@link JSONArray} has only
1394+
* one element, then the array will be output on a single line:
1395+
* <pre>{@code [1]}</pre>
1396+
*
1397+
* <p>If an array has 2 or more elements, then it will be output across
1398+
* multiple lines: <pre>{@code
1399+
* [
1400+
* 1,
1401+
* "value 2",
1402+
* 3
1403+
* ]
1404+
* }</pre>
1405+
* <p><b>
13771406
* Warning: This method assumes that the data structure is acyclical.
1407+
* </b>
13781408
*
13791409
* @param writer
13801410
* Writes the serialized JSON

JSONML.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ private static Object parse(
172172
if (!(token instanceof String)) {
173173
throw x.syntaxError("Missing value");
174174
}
175-
newjo.accumulate(attribute, keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token));
175+
newjo.accumulate(attribute, keepStrings ? ((String)token) :XML.stringToValue((String)token));
176176
token = null;
177177
} else {
178178
newjo.accumulate(attribute, "");

JSONObject.java

+105-37
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.json;
22

3+
import java.io.Closeable;
4+
35
/*
46
Copyright (c) 2002 JSON.org
57
@@ -28,6 +30,7 @@ of this software and associated documentation files (the "Software"), to deal
2830
import java.io.StringWriter;
2931
import java.io.Writer;
3032
import java.lang.reflect.Field;
33+
import java.lang.reflect.InvocationTargetException;
3134
import java.lang.reflect.Method;
3235
import java.lang.reflect.Modifier;
3336
import java.math.BigDecimal;
@@ -228,7 +231,21 @@ public JSONObject(JSONTokener x) throws JSONException {
228231
if (c != ':') {
229232
throw x.syntaxError("Expected a ':' after a key");
230233
}
231-
this.putOnce(key, x.nextValue());
234+
235+
// Use syntaxError(..) to include error location
236+
237+
if (key != null) {
238+
// Check if key exists
239+
if (this.opt(key) != null) {
240+
// key already exists
241+
throw x.syntaxError("Duplicate key \"" + key + "\"");
242+
}
243+
// Only add value if non-null
244+
Object value = x.nextValue();
245+
if (value!=null) {
246+
this.put(key, value);
247+
}
248+
}
232249

233250
// Pairs are separated by ','.
234251

@@ -276,16 +293,19 @@ public JSONObject(Map<?, ?> m) {
276293
* <code>"is"</code> followed by an uppercase letter, the method is invoked,
277294
* and a key and the value returned from the getter method are put into the
278295
* new JSONObject.
279-
*
296+
* <p>
280297
* The key is formed by removing the <code>"get"</code> or <code>"is"</code>
281298
* prefix. If the second remaining character is not upper case, then the
282299
* first character is converted to lower case.
283-
*
300+
* <p>
284301
* For example, if an object has a method named <code>"getName"</code>, and
285302
* if the result of calling <code>object.getName()</code> is
286303
* <code>"Larry Fine"</code>, then the JSONObject will contain
287304
* <code>"name": "Larry Fine"</code>.
288-
*
305+
* <p>
306+
* Methods that return <code>void</code> as well as <code>static</code>
307+
* methods are ignored.
308+
*
289309
* @param bean
290310
* An object that has getter methods that should be used to make
291311
* a JSONObject.
@@ -1388,6 +1408,15 @@ public String optString(String key, String defaultValue) {
13881408
return NULL.equals(object) ? defaultValue : object.toString();
13891409
}
13901410

1411+
/**
1412+
* Populates the internal map of the JSONObject with the bean properties.
1413+
* The bean can not be recursive.
1414+
*
1415+
* @see JSONObject#JSONObject(Object)
1416+
*
1417+
* @param bean
1418+
* the bean
1419+
*/
13911420
private void populateMap(Object bean) {
13921421
Class<?> klass = bean.getClass();
13931422

@@ -1397,39 +1426,52 @@ private void populateMap(Object bean) {
13971426

13981427
Method[] methods = includeSuperClass ? klass.getMethods() : klass
13991428
.getDeclaredMethods();
1400-
for (int i = 0; i < methods.length; i += 1) {
1401-
try {
1402-
Method method = methods[i];
1403-
if (Modifier.isPublic(method.getModifiers())) {
1404-
String name = method.getName();
1405-
String key = "";
1406-
if (name.startsWith("get")) {
1407-
if ("getClass".equals(name)
1408-
|| "getDeclaringClass".equals(name)) {
1409-
key = "";
1410-
} else {
1411-
key = name.substring(3);
1412-
}
1413-
} else if (name.startsWith("is")) {
1414-
key = name.substring(2);
1429+
for (final Method method : methods) {
1430+
final int modifiers = method.getModifiers();
1431+
if (Modifier.isPublic(modifiers)
1432+
&& !Modifier.isStatic(modifiers)
1433+
&& method.getParameterTypes().length == 0
1434+
&& !method.isBridge()
1435+
&& method.getReturnType() != Void.TYPE ) {
1436+
final String name = method.getName();
1437+
String key;
1438+
if (name.startsWith("get")) {
1439+
if ("getClass".equals(name) || "getDeclaringClass".equals(name)) {
1440+
continue;
1441+
}
1442+
key = name.substring(3);
1443+
} else if (name.startsWith("is")) {
1444+
key = name.substring(2);
1445+
} else {
1446+
continue;
1447+
}
1448+
if (key.length() > 0
1449+
&& Character.isUpperCase(key.charAt(0))) {
1450+
if (key.length() == 1) {
1451+
key = key.toLowerCase(Locale.ROOT);
1452+
} else if (!Character.isUpperCase(key.charAt(1))) {
1453+
key = key.substring(0, 1).toLowerCase(Locale.ROOT)
1454+
+ key.substring(1);
14151455
}
1416-
if (key.length() > 0
1417-
&& Character.isUpperCase(key.charAt(0))
1418-
&& method.getParameterTypes().length == 0) {
1419-
if (key.length() == 1) {
1420-
key = key.toLowerCase(Locale.ROOT);
1421-
} else if (!Character.isUpperCase(key.charAt(1))) {
1422-
key = key.substring(0, 1).toLowerCase(Locale.ROOT)
1423-
+ key.substring(1);
1424-
}
14251456

1426-
Object result = method.invoke(bean, (Object[]) null);
1457+
try {
1458+
final Object result = method.invoke(bean);
14271459
if (result != null) {
14281460
this.map.put(key, wrap(result));
1461+
// we don't use the result anywhere outside of wrap
1462+
// if it's a resource we should be sure to close it after calling toString
1463+
if(result instanceof Closeable) {
1464+
try {
1465+
((Closeable)result).close();
1466+
} catch (IOException ignore) {
1467+
}
1468+
}
14291469
}
1470+
} catch (IllegalAccessException ignore) {
1471+
} catch (IllegalArgumentException ignore) {
1472+
} catch (InvocationTargetException ignore) {
14301473
}
14311474
}
1432-
} catch (Exception ignore) {
14331475
}
14341476
}
14351477
}
@@ -1676,7 +1718,7 @@ public Object optQuery(String jsonPointer) {
16761718
* Queries and returns a value from this object using {@code jsonPointer}, or
16771719
* returns null if the query fails due to a missing key.
16781720
*
1679-
* @param The JSON pointer
1721+
* @param jsonPointer The JSON pointer
16801722
* @return the queried value or {@code null}
16811723
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
16821724
*/
@@ -2004,9 +2046,10 @@ public JSONArray toJSONArray(JSONArray names) throws JSONException {
20042046
* Make a JSON text of this JSONObject. For compactness, no whitespace is
20052047
* added. If this would not result in a syntactically correct JSON text,
20062048
* then null will be returned instead.
2007-
* <p>
2049+
* <p><b>
20082050
* Warning: This method assumes that the data structure is acyclical.
2009-
*
2051+
* </b>
2052+
*
20102053
* @return a printable, displayable, portable, transmittable representation
20112054
* of the object, beginning with <code>{</code>&nbsp;<small>(left
20122055
* brace)</small> and ending with <code>}</code>&nbsp;<small>(right
@@ -2023,8 +2066,20 @@ public String toString() {
20232066

20242067
/**
20252068
* Make a pretty-printed JSON text of this JSONObject.
2026-
* <p>
2069+
*
2070+
* <p>If <code>indentFactor > 0</code> and the {@link JSONObject}
2071+
* has only one key, then the object will be output on a single line:
2072+
* <pre>{@code {"key": 1}}</pre>
2073+
*
2074+
* <p>If an object has 2 or more keys, then it will be output across
2075+
* multiple lines: <code><pre>{
2076+
* "key1": 1,
2077+
* "key2": "value 2",
2078+
* "key3": 3
2079+
* }</pre></code>
2080+
* <p><b>
20272081
* Warning: This method assumes that the data structure is acyclical.
2082+
* </b>
20282083
*
20292084
* @param indentFactor
20302085
* The number of spaces to add to each level of indentation.
@@ -2130,9 +2185,10 @@ public static Object wrap(Object object) {
21302185
/**
21312186
* Write the contents of the JSONObject as JSON text to a writer. For
21322187
* compactness, no whitespace is added.
2133-
* <p>
2188+
* <p><b>
21342189
* Warning: This method assumes that the data structure is acyclical.
2135-
*
2190+
* </b>
2191+
*
21362192
* @return The writer.
21372193
* @throws JSONException
21382194
*/
@@ -2196,8 +2252,20 @@ static final void indent(Writer writer, int indent) throws IOException {
21962252

21972253
/**
21982254
* Write the contents of the JSONObject as JSON text to a writer.
2199-
* <p>
2255+
*
2256+
* <p>If <code>indentFactor > 0</code> and the {@link JSONObject}
2257+
* has only one key, then the object will be output on a single line:
2258+
* <pre>{@code {"key": 1}}</pre>
2259+
*
2260+
* <p>If an object has 2 or more keys, then it will be output across
2261+
* multiple lines: <code><pre>{
2262+
* "key1": 1,
2263+
* "key2": "value 2",
2264+
* "key3": 3
2265+
* }</pre></code>
2266+
* <p><b>
22002267
* Warning: This method assumes that the data structure is acyclical.
2268+
* </b>
22012269
*
22022270
* @param writer
22032271
* Writes the serialized JSON

README

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ invalid number formats (1.2e6.3) will cause errors as such documents can not be
8989
reliably.
9090

9191
Release history:
92+
20171018 Checkpoint for recent commits.
93+
9294
20170516 Roll up recent commits.
9395

9496
20160810 Revert code that was breaking opt*() methods.

0 commit comments

Comments
 (0)