-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JSONObject#populateMap() calls methods that aren't valid object getters #279
Comments
I think the idea of more careful handling of beans is reasonable. Don't know if we can be sure that no users will ever want to serialize static data. For example, suppose there is only one instance of the class, and its data is static? Making sure the method has a return type sounds reasonable. Not sure why synthetic methods must be excluded from serialization. Can you give an example? Might also want to address enum serialization as a bean, which I think picks up some unwanted getters. |
I think this ties in a little with #264. For Statics: Void return types: Synthetic Methods: |
In a slightly broader context, I have doubts about if supporting bean <-> JSONObject conversions is a good idea at all. Maybe, for the sake of simplicity, Maybe it would be a better idea to deprecate the |
@erosb I personally do not use the constructor. I've been using my own custom bean -> JSONObject wrapper for around 10 years now. Mine does 2 of the 3 checks (no statics, and no void returns) mentioned above. However, I think due to the handover agreement with Douglas, we can not deprecate the constructor. Bug fixes should be fine in it, but I don't think we are allowed to reduce the public API. |
For reference, here is the code I use to determine what methods to skip: /**
* @param m
* method to check
* @return true if the method does not match expected properties
*/
private static boolean skip(final Method m) {
final int modifiers = m.getModifiers();
if (
// skip static
Modifier.isStatic(modifiers)
// skip abstract
|| Modifier.isAbstract(modifiers)
// skip any non-public methods
|| !Modifier.isPublic(modifiers)
// skip methods with parameters
|| m.getParameterTypes().length != 0) {
return true;
}
final Class<?> returnType = m.getReturnType();
// skip void, collections, maps
if (void.class.equals(returnType) || Collection.class.isAssignableFrom(returnType)
|| Map.class.isAssignableFrom(returnType)) {
return true;
}
final String name = m.getName();
if ("hashCode".equals(name) || "getClass".equals(name)
|| !(name.startsWith("get") || name.startsWith("is")
|| name.startsWith("has"))
) {
return true;
}
return false;
} I skip maps and collections because I use this mainly in a REST application and any associated maps/collections are loaded by other web actions. I don't think skipping them would be the right thing to do for --edit |
Looking up synthetic methods I found this: http://www.javaworld.com/article/2073578/java-s-synthetic-methods.html I'm still not sure that skipping them is the best option. From what I've seen, usually compiler generated methods and classes start with a $, so the current checks on names would exclude them in most cases. I suppose that would be compiler dependant though, and maybe not something we want to rely on? |
Perhaps instead of synthetic method, read bridge method. All bridge methods are synthetic methods, but not all synthetic methods are bridge methods. Bridge methods are generated by the javac compiler as a result of Java 5's greater flexibility in overriding methods based on return types. As an example, given a superclass that looks like this:
And a subclass that looks like this:
Note that How this affects The code I have to skip these methods looks like this:
|
+1 for omitting syntetic methods. Conceptually these are methods which are not written by the developer of the class, probably he/she is not even know about its existence. Syntetic methods exist for solely technical, java-specific reasons (see hte above bridge method explanation), therefore mapping them while working with a language-independent representation of the bean is just not useful. I'm quite sure about that a lot of users of this library don't even know about of syntethic methods, and current behavior may result un unpleasant surprises. |
Static methods: No plans to change |
JSONObject.populateMap() can be a over-enthusiastic in calling methods on an object that aren't valid bean getter methods. For instance:
My opinion is that populateMap() should be more cautious about calling methods on an unknown object. There may be side-effecty behaviour within the object that's undesirable. Code to avoid doing this is trivial and fast.
The text was updated successfully, but these errors were encountered: