1
1
package org .json ;
2
2
3
+ import java .io .Closeable ;
4
+
3
5
/*
4
6
Copyright (c) 2002 JSON.org
5
7
@@ -28,6 +30,7 @@ of this software and associated documentation files (the "Software"), to deal
28
30
import java .io .StringWriter ;
29
31
import java .io .Writer ;
30
32
import java .lang .reflect .Field ;
33
+ import java .lang .reflect .InvocationTargetException ;
31
34
import java .lang .reflect .Method ;
32
35
import java .lang .reflect .Modifier ;
33
36
import java .math .BigDecimal ;
@@ -276,16 +279,19 @@ public JSONObject(Map<?, ?> m) {
276
279
* <code>"is"</code> followed by an uppercase letter, the method is invoked,
277
280
* and a key and the value returned from the getter method are put into the
278
281
* new JSONObject.
279
- *
282
+ * <p>
280
283
* The key is formed by removing the <code>"get"</code> or <code>"is"</code>
281
284
* prefix. If the second remaining character is not upper case, then the
282
285
* first character is converted to lower case.
283
- *
286
+ * <p>
284
287
* For example, if an object has a method named <code>"getName"</code>, and
285
288
* if the result of calling <code>object.getName()</code> is
286
289
* <code>"Larry Fine"</code>, then the JSONObject will contain
287
290
* <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
+ *
289
295
* @param bean
290
296
* An object that has getter methods that should be used to make
291
297
* a JSONObject.
@@ -1388,6 +1394,15 @@ public String optString(String key, String defaultValue) {
1388
1394
return NULL .equals (object ) ? defaultValue : object .toString ();
1389
1395
}
1390
1396
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
+ */
1391
1406
private void populateMap (Object bean ) {
1392
1407
Class <?> klass = bean .getClass ();
1393
1408
@@ -1397,39 +1412,52 @@ private void populateMap(Object bean) {
1397
1412
1398
1413
Method [] methods = includeSuperClass ? klass .getMethods () : klass
1399
1414
.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 );
1415
1441
}
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
- }
1425
1442
1426
- Object result = method .invoke (bean , (Object []) null );
1443
+ try {
1444
+ final Object result = method .invoke (bean );
1427
1445
if (result != null ) {
1428
1446
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
+ }
1429
1455
}
1456
+ } catch (IllegalAccessException ignore ) {
1457
+ } catch (IllegalArgumentException ignore ) {
1458
+ } catch (InvocationTargetException ignore ) {
1430
1459
}
1431
1460
}
1432
- } catch (Exception ignore ) {
1433
1461
}
1434
1462
}
1435
1463
}
0 commit comments