From 643b25140f84231667683b8c8179eb1809b710cb Mon Sep 17 00:00:00 2001 From: "John J. Aylward" Date: Fri, 7 Jul 2017 20:48:42 -0400 Subject: [PATCH 1/5] Updates for populateMap based on discussion in #279 and #264 --- JSONObject.java | 55 ++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/JSONObject.java b/JSONObject.java index 8ad7864df..69c6993a7 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -28,6 +28,7 @@ of this software and associated documentation files (the "Software"), to deal import java.io.StringWriter; import java.io.Writer; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.math.BigDecimal; @@ -1397,39 +1398,41 @@ private void populateMap(Object bean) { Method[] methods = includeSuperClass ? klass.getMethods() : klass .getDeclaredMethods(); - for (int i = 0; i < methods.length; i += 1) { - try { - Method method = methods[i]; - if (Modifier.isPublic(method.getModifiers())) { - String name = method.getName(); - String key = ""; - if (name.startsWith("get")) { - if ("getClass".equals(name) - || "getDeclaringClass".equals(name)) { - key = ""; - } else { - key = name.substring(3); - } - } else if (name.startsWith("is")) { - key = name.substring(2); + for (final Method method : methods) { + final int modifiers = method.getModifiers(); + if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers) + && method.getParameterTypes().length == 0 && !method.isBridge() + && method.getReturnType() != Void.TYPE ) { + final String name = method.getName(); + String key; + if (name.startsWith("get")) { + if ("getClass".equals(name) || "getDeclaringClass".equals(name)) { + continue; + } + key = name.substring(3); + } else if (name.startsWith("is")) { + key = name.substring(2); + } else { + continue; + } + if (key.length() > 0 && Character.isUpperCase(key.charAt(0))) { + if (key.length() == 1) { + key = key.toLowerCase(Locale.ROOT); + } else if (!Character.isUpperCase(key.charAt(1))) { + key = key.substring(0, 1).toLowerCase(Locale.ROOT) + + key.substring(1); } - if (key.length() > 0 - && Character.isUpperCase(key.charAt(0)) - && method.getParameterTypes().length == 0) { - if (key.length() == 1) { - key = key.toLowerCase(Locale.ROOT); - } else if (!Character.isUpperCase(key.charAt(1))) { - key = key.substring(0, 1).toLowerCase(Locale.ROOT) - + key.substring(1); - } - Object result = method.invoke(bean, (Object[]) null); + try { + final Object result = method.invoke(bean); if (result != null) { this.map.put(key, wrap(result)); } + } catch (IllegalAccessException ignore) { + } catch (IllegalArgumentException ignore) { + } catch (InvocationTargetException ignore) { } } - } catch (Exception ignore) { } } } From 641b68dd55c0682c3ca32034347fd1972131b123 Mon Sep 17 00:00:00 2001 From: "John J. Aylward" Date: Fri, 7 Jul 2017 21:15:11 -0400 Subject: [PATCH 2/5] updates javadoc. --- JSONObject.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/JSONObject.java b/JSONObject.java index 69c6993a7..ef2413a1c 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -277,16 +277,19 @@ public JSONObject(Map m) { * "is" followed by an uppercase letter, the method is invoked, * and a key and the value returned from the getter method are put into the * new JSONObject. - * + *

* The key is formed by removing the "get" or "is" * prefix. If the second remaining character is not upper case, then the * first character is converted to lower case. - * + *

* For example, if an object has a method named "getName", and * if the result of calling object.getName() is * "Larry Fine", then the JSONObject will contain * "name": "Larry Fine". - * + *

+ * Methods that return void as well as static + * methods are ignored. + * * @param bean * An object that has getter methods that should be used to make * a JSONObject. @@ -1389,6 +1392,15 @@ public String optString(String key, String defaultValue) { return NULL.equals(object) ? defaultValue : object.toString(); } + /** + * Populates the internal map of the JSONObject with the bean properties. + * The bean can not be recursive. + * + * @see JSONObject#JSONObject(Object) + * + * @param bean + * the bean + */ private void populateMap(Object bean) { Class klass = bean.getClass(); From a129ebe8e47df8121fdc3f37801610f682d57ae5 Mon Sep 17 00:00:00 2001 From: "John J. Aylward" Date: Sun, 9 Jul 2017 17:36:36 -0400 Subject: [PATCH 3/5] Adds check for resources opened by our bean mapping --- JSONObject.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/JSONObject.java b/JSONObject.java index ef2413a1c..171f293e8 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -1,5 +1,7 @@ package org.json; +import java.io.Closeable; + /* Copyright (c) 2002 JSON.org @@ -1412,8 +1414,10 @@ private void populateMap(Object bean) { .getDeclaredMethods(); for (final Method method : methods) { final int modifiers = method.getModifiers(); - if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers) - && method.getParameterTypes().length == 0 && !method.isBridge() + if (Modifier.isPublic(modifiers) + && !Modifier.isStatic(modifiers) + && method.getParameterTypes().length == 0 + && !method.isBridge() && method.getReturnType() != Void.TYPE ) { final String name = method.getName(); String key; @@ -1427,7 +1431,8 @@ private void populateMap(Object bean) { } else { continue; } - if (key.length() > 0 && Character.isUpperCase(key.charAt(0))) { + if (key.length() > 0 + && Character.isUpperCase(key.charAt(0))) { if (key.length() == 1) { key = key.toLowerCase(Locale.ROOT); } else if (!Character.isUpperCase(key.charAt(1))) { @@ -1439,6 +1444,14 @@ private void populateMap(Object bean) { final Object result = method.invoke(bean); if (result != null) { this.map.put(key, wrap(result)); + // we don't use the result anywhere outside of wrap + // if it's a resource we should be sure to close it after calling toString + if(result instanceof Closeable) { + try { + ((Closeable)result).close(); + } catch (IOException ignore) { + } + } } } catch (IllegalAccessException ignore) { } catch (IllegalArgumentException ignore) { From 5c80c9157d86b5f22bf5b905b23a4039d37de348 Mon Sep 17 00:00:00 2001 From: "John J. Aylward" Date: Sun, 9 Jul 2017 18:47:09 -0400 Subject: [PATCH 4/5] fixes malformed javadoc --- JSONArray.java | 2 +- JSONObject.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/JSONArray.java b/JSONArray.java index a402d6714..197ad977d 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -1230,7 +1230,7 @@ public Object optQuery(String jsonPointer) { * Queries and returns a value from this object using {@code jsonPointer}, or * returns null if the query fails due to a missing key. * - * @param The JSON pointer + * @param jsonPointer The JSON pointer * @return the queried value or {@code null} * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax */ diff --git a/JSONObject.java b/JSONObject.java index 171f293e8..800e58985 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -1704,7 +1704,7 @@ public Object optQuery(String jsonPointer) { * Queries and returns a value from this object using {@code jsonPointer}, or * returns null if the query fails due to a missing key. * - * @param The JSON pointer + * @param jsonPointer The JSON pointer * @return the queried value or {@code null} * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax */ From 4dbc5ef8036017c05c107d5e62be322213726930 Mon Sep 17 00:00:00 2001 From: "John J. Aylward" Date: Sun, 9 Jul 2017 18:48:40 -0400 Subject: [PATCH 5/5] fixes malformed javadoc --- XML.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/XML.java b/XML.java index 4dd9a2c7c..36f44c80e 100644 --- a/XML.java +++ b/XML.java @@ -423,7 +423,7 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, bool } /** - * This method is the same as {@link JSONObject.stringToValue(String)} + * This method is the same as {@link JSONObject#stringToValue(String)} * except that this also tries to unescape String values. * * @param string String to convert