11package 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
2830import java .io .StringWriter ;
2931import java .io .Writer ;
3032import java .lang .reflect .Field ;
33+ import java .lang .reflect .InvocationTargetException ;
3134import java .lang .reflect .Method ;
3235import java .lang .reflect .Modifier ;
3336import 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 }
0 commit comments