Reputation: 695
I have a LinkedHashMap<MyKey, MyValue>
, MyKey and MyValue are the POJOs.
MyKey is a bean which has getters and setters, it also has overridden hashcode() method. I read somewhere that Map will use hashcode() of object to form key, so if i write fromJson... how exactly is it reading it?
In MyKey i have defined following function:
@JsonCreator
public static MyKey fromJSON(String val) throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
MyKey a = mapper.readValue(val,MyKey .class);
return a;
}
The Serialized Json String is going as {"MyKey@3":{MyValue.. json string}}.
I am getting following exception trace:
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
at org.codehaus.jackson.map.deser.StdDeserializationContext.weirdKeyException(StdDeserializationContext.java:234)
at org.codehaus.jackson.map.deser.StdKeyDeserializer.deserializeKey(StdKeyDeserializer.java:34)
at org.codehaus.jackson.map.deser.MapDeserializer._readAndBind(MapDeserializer.java:223)
at org.codehaus.jackson.map.deser.MapDeserializer.deserialize(MapDeserializer.java:165)
at org.codehaus.jackson.map.deser.MapDeserializer.deserialize(MapDeserializer.java:25)
at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:252)
at org.codehaus.jackson.map.deser.SettableBeanProperty$MethodProperty.deserializeAndSet(SettableBeanProperty.java:356)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:494)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:368)
at org.codehaus.jackson.map.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:77)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeWithType(BeanDeserializer.java:423)
at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:250)
at org.codehaus.jackson.map.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:595)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:472)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:368)
at org.codehaus.jackson.map.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:77)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeWithType(BeanDeserializer.java:423)
at org.codehaus.jackson.map.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:250)
at org.codehaus.jackson.map.deser.SettableBeanProperty$MethodProperty.deserializeAndSet(SettableBeanProperty.java:356)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:494)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:368)
at org.codehaus.jackson.map.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:77)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeWithType(BeanDeserializer.java:423)
at org.codehaus.jackson.map.deser.StdDeserializerProvider$WrappedDeserializer.deserialize(StdDeserializerProvider.java:460)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2395)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1595)
How should i fix this? I would prefer not to register json serializer or deserializer if possible.
Upvotes: 0
Views: 558
Reputation: 2834
Well, perhaps the Exception message is not very clear, but what actually happens is you get a StackOverFlow that gets catched and Jackson instead throws a weirdKeyException.
The problem is your JsonCreator: you can't use the ObjectMapper in your method because that will simply call the JsonCreator again and again and again. What you should do instead is something like the following:
@JsonCreator
public static MyKey fromJSON(String val) throws JsonParseException, JsonMappingException, IOException {
return new MyKey(val);
}
Update: Since it didn't appear to be clear I'll try to explain a bit more the control flow.
What happens in this case is that the databinding functionnality of Jackson (with ObjectMapper) gets called recursively. The fromJSON is called during databinding because it is annotated with JsonCreator; any time you try to create an instance of MyKey with Jackson that method will be called. So, when you try
MyKey a = mapper.readValue(val,MyKey .class);
Jackson will call fromJSON, because that's how it knows to create MyKey.
As a rule of thumb, I avoid using Jackson functionality inside of methods that have annotations for Jackson, that's just asking for trouble. When you do you need to be extra careful because of the implicit recursion like this one.
Upvotes: 2