jens.ha...@gmail.com
unread,Feb 22, 2013, 7:46:43 PM2/22/13Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Sign in to report message
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to gen...@googlegroups.com
Hi Eugen,
first of all: thanks for creating this fantastic tool. I am trying to serialize very heterogeneous polymorphic objects, and where flexjson and jackson left me stranded, genson picked up.
However, I noticed a few issues, which create very unexpected errors. Please let me know if you need more detail on any of these.
1. [Bug] A class that has a "setter" with an empty parameter list leads to an exception during serialization.
Example:
class Foo {
Integer bar;
Integer getBar() {
return bar;
}
void setBar(Integer bar) {
this.bar = bar;
}
/* erroneously considered to be a setter */
void setToNull() {
this.bar = null;
}
}
java.lang.ArrayIndexOutOfBoundsException: 0
at com.owlike.genson.Genson$Builder$2.isMutator(Genson.java:799)
at com.owlike.genson.reflect.BeanMutatorAccessorResolver$CompositeResolver.isMutator(BeanMutatorAccessorResolver.java:166)
at com.owlike.genson.reflect.BaseBeanDescriptorProvider.provideMethodMutators(BaseBeanDescriptorProvider.java:264)
at com.owlike.genson.reflect.BaseBeanDescriptorProvider.provideBeanPropertyMutators(BaseBeanDescriptorProvider.java:102)
at com.owlike.genson.reflect.AbstractBeanDescriptorProvider.provide(AbstractBeanDescriptorProvider.java:51)
at com.owlike.genson.convert.BasicConvertersFactory.provide(BasicConvertersFactory.java:109)
at com.owlike.genson.convert.BasicConvertersFactory.create(BasicConvertersFactory.java:74)
at com.owlike.genson.convert.BasicConvertersFactory.create(BasicConvertersFactory.java:56)
at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:93)
at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:80)
at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:93)
at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:80)
at com.owlike.genson.convert.CircularClassReferenceConverterFactory.create(CircularClassReferenceConverterFactory.java:58)
at com.owlike.genson.convert.CircularClassReferenceConverterFactory.create(CircularClassReferenceConverterFactory.java:22)
at com.owlike.genson.Genson.provideConverter(Genson.java:182)
at com.owlike.genson.Genson.serialize(Genson.java:279)
at com.owlike.genson.Genson.serialize(Genson.java:207)
Current workaround: "Mask out" the offending setXXX method, like so:
Genson genson = new Genson.Builder().exclude("toNull");
Suggested fix: In the isMutator method, check for the size of the parameter list and return false, so setToNull is (rightfully) no longer considered a setter.
2. [Bug] A class with a generic that implements Comparable (a fairly common case) leads to a stack overflow during deserialization, because of the self-referential generic type.
class Interval<T extends Comparable<T>> {
T min;
T max;
public T getMin() { return min;}
public T getMax() { return max;}
public void setMin(T min) { this.min = min; }
public void setMax(T max) { this.max = max; }
}
com.owlike.genson.TransformationException: Could not deserialize to property 'signatures' of class class ca.mda.sva.common.domain.alerts.AlertDuplicateIdentity
at com.owlike.genson.reflect.PropertyMutator.couldNotDeserialize(PropertyMutator.java:58)
at com.owlike.genson.reflect.PropertyMutator.deserialize(PropertyMutator.java:41)
at com.owlike.genson.reflect.BeanDescriptor.deserialize(BeanDescriptor.java:116)
at com.owlike.genson.reflect.BeanDescriptor.deserialize(BeanDescriptor.java:98)
at com.owlike.genson.convert.ClassMetadataConverter.deserialize(ClassMetadataConverter.java:103)
at com.owlike.genson.convert.NullConverter$NullConverterWrapper.deserialize(NullConverter.java:61)
at com.owlike.genson.convert.ClassMetadataConverter.deserialize(ClassMetadataConverter.java:95)
at com.owlike.genson.convert.NullConverter$NullConverterWrapper.deserialize(NullConverter.java:61)
at com.owlike.genson.Genson.deserialize(Genson.java:331)
at com.owlike.genson.Genson.deserialize(Genson.java:296)
Caused by: java.lang.StackOverflowError
at sun.reflect.generics.reflectiveObjects.TypeVariableImpl.hashCode(Unknown Source)
at com.owlike.genson.reflect.TypeUtil$TypeAndRootClassKey.<init>(TypeUtil.java:467)
at com.owlike.genson.reflect.TypeUtil.expandType(TypeUtil.java:56)
at com.owlike.genson.reflect.TypeUtil.expandType(TypeUtil.java:66)
at com.owlike.genson.reflect.TypeUtil.expandType(TypeUtil.java:90)
at com.owlike.genson.reflect.TypeUtil.expandType(TypeUtil.java:66)
at com.owlike.genson.reflect.TypeUtil.expandType(TypeUtil.java:90)
at com.owlike.genson.reflect.TypeUtil.expandType(TypeUtil.java:66)
....
Note: expandType() is alternately called with type=Comparable<T> and type=T.
Current workaround: Create a marker class that instantiates T with a concrete type, for each instantiating class for T used in any type to be serialized (ugly, but works for me for the time being).
Suggested fix: To break the self-referentiality, create the ExpandedParameterizedType first, and keep a HashMap of mappings
Type->corresponding ExpandedType. Don't include the type args in the constructor, but recursively expand the type arguments first,
then set them via a setter setTypeArgs(Type[] typeArgs).
Upon re-encountering the previously encountered type T (or perhaps Comparable<T>) in the recursion, close the loop by referring to the already created ExpandedParameterizedType.
(Of course, this means that you now have a circular link in your ExpandedParameterizedType hierarchy, and I am not sure what that will do to your deserialization code.)
3. [Feature Request] Allow Genson to serialize any map (currently, only HashMaps whose keys are strings are supported).
My workaround is to create a ConverterFactory for a Map<K,V>, whose converter serializes a map into an array of key-value pairs, like so:
Java:
package my.package;
HashMap<MyKeyClass, MyValueClass> myMap;
Json:
"myMap":{
"@class":"java.util.HashMap",
"map":[
{"key":{"@class":"my.package.MyKeyClass","arg1":val1,"arg2":val2,...},
"value":{"@class":"my.package.MyValueClass","arg3":val3,"arg4":val4,...}},
...
{"key":{"@class":"my.package.MyKeyClass","arg1":val11,"arg2":val22,...},
"value":{"@class":"my.package.MyValueClass","arg3":val33,"arg4":val44,...}}]}
I could make this ConverterFactory available.