Skip to content

Commit d9b8507

Browse files
authored
Merge pull request stleary#354 from johnjaylward/PopulateMapMoreStrict
Updates for populateMap based on discussion in stleary#279 and stleary#264
2 parents d345bc5 + 4dbc5ef commit d9b8507

File tree

2 files changed

+58
-30
lines changed

2 files changed

+58
-30
lines changed

JSONObject.java

Lines changed: 57 additions & 29 deletions
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;
@@ -276,16 +279,19 @@ public JSONObject(Map<?, ?> m) {
276279
* <code>"is"</code> followed by an uppercase letter, the method is invoked,
277280
* and a key and the value returned from the getter method are put into the
278281
* new JSONObject.
279-
*
282+
* <p>
280283
* The key is formed by removing the <code>"get"</code> or <code>"is"</code>
281284
* prefix. If the second remaining character is not upper case, then the
282285
* first character is converted to lower case.
283-
*
286+
* <p>
284287
* For example, if an object has a method named <code>"getName"</code>, and
285288
* if the result of calling <code>object.getName()</code> is
286289
* <code>"Larry Fine"</code>, then the JSONObject will contain
287290
* <code>"name": "Larry Fine"</code>.
288-
*
291+
* <p>
292+
* Methods that return <code>void</code> as well as <code>static</code>
293+
* methods are ignored.
294+
*
289295
* @param bean
290296
* An object that has getter methods that should be used to make
291297
* a JSONObject.
@@ -1388,6 +1394,15 @@ public String optString(String key, String defaultValue) {
13881394
return NULL.equals(object) ? defaultValue : object.toString();
13891395
}
13901396

1397+
/**
1398+
* Populates the internal map of the JSONObject with the bean properties.
1399+
* The bean can not be recursive.
1400+
*
1401+
* @see JSONObject#JSONObject(Object)
1402+
*
1403+
* @param bean
1404+
* the bean
1405+
*/
13911406
private void populateMap(Object bean) {
13921407
Class<?> klass = bean.getClass();
13931408

@@ -1397,39 +1412,52 @@ private void populateMap(Object bean) {
13971412

13981413
Method[] methods = includeSuperClass ? klass.getMethods() : klass
13991414
.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);
1415+
for (final Method method : methods) {
1416+
final int modifiers = method.getModifiers();
1417+
if (Modifier.isPublic(modifiers)
1418+
&& !Modifier.isStatic(modifiers)
1419+
&& method.getParameterTypes().length == 0
1420+
&& !method.isBridge()
1421+
&& method.getReturnType() != Void.TYPE ) {
1422+
final String name = method.getName();
1423+
String key;
1424+
if (name.startsWith("get")) {
1425+
if ("getClass".equals(name) || "getDeclaringClass".equals(name)) {
1426+
continue;
1427+
}
1428+
key = name.substring(3);
1429+
} else if (name.startsWith("is")) {
1430+
key = name.substring(2);
1431+
} else {
1432+
continue;
1433+
}
1434+
if (key.length() > 0
1435+
&& Character.isUpperCase(key.charAt(0))) {
1436+
if (key.length() == 1) {
1437+
key = key.toLowerCase(Locale.ROOT);
1438+
} else if (!Character.isUpperCase(key.charAt(1))) {
1439+
key = key.substring(0, 1).toLowerCase(Locale.ROOT)
1440+
+ key.substring(1);
14151441
}
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-
}
14251442

1426-
Object result = method.invoke(bean, (Object[]) null);
1443+
try {
1444+
final Object result = method.invoke(bean);
14271445
if (result != null) {
14281446
this.map.put(key, wrap(result));
1447+
// we don't use the result anywhere outside of wrap
1448+
// if it's a resource we should be sure to close it after calling toString
1449+
if(result instanceof Closeable) {
1450+
try {
1451+
((Closeable)result).close();
1452+
} catch (IOException ignore) {
1453+
}
1454+
}
14291455
}
1456+
} catch (IllegalAccessException ignore) {
1457+
} catch (IllegalArgumentException ignore) {
1458+
} catch (InvocationTargetException ignore) {
14301459
}
14311460
}
1432-
} catch (Exception ignore) {
14331461
}
14341462
}
14351463
}

XML.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, bool
423423
}
424424

425425
/**
426-
* This method is the same as {@link JSONObject.stringToValue(String)}
426+
* This method is the same as {@link JSONObject#stringToValue(String)}
427427
* except that this also tries to unescape String values.
428428
*
429429
* @param string String to convert

0 commit comments

Comments
 (0)