31346

Json - weired key exception?

Question:

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.

Answer1:

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); }

<strong>Update</strong>: 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.

Recommend

  • Conflicting getter definitions for property in Jackson 2.2.3
  • Deserializing json embedded node as value into Map using Jackson
  • golang struct concurrent read and write without Lock is also running ok?
  • Deserializing JSON into a class with a generic argument using GSON or Jackson
  • Android: Having Difficulty passing an Object from one activity to another using Parcel
  • java.lang.IllegalArgumentException: number of arguments must be even at org.javalite.activejdbc.Mode
  • Boost deserialize a derived class to base class pointer
  • How enable GZIP compression for Spring HttpInvoker requests using Tomcat?
  • Json.net Add property to every class containing of a certain type
  • How java jackson deserializer handle both Boolean and Object on same field
  • Use Jackson to deserialize JSON string or object into a String field
  • Mapping JSON to Java Object return null value
  • Jackson (JSON) throws JsonMappingException when Float is null
  • Gson serializing Spring beans
  • Unzip archive in .Net CORE 1.0
  • Telegram bot API - Inline bot getting Error 400 while trying to answer inline query
  • Select value from xtype selection type checkbox CQ5
  • Javascript CORS - No 'Access-Control-Allow-Origin' header is present
  • Exception creating JSON with LINQ
  • Angular2 Response for preflight is invalid (redirect) from some GET requests
  • chrome.tabs.executeScript only fires when the Developer Console is open
  • Play WS (2.2.1): post/put large request
  • Different response to non-authenticated users and AJAX calls
  • How to set my toolbar fixed while scrolling android
  • Warning: Can't call setState (or forceUpdate) on an unmounted component
  • AT Commands to Send SMS not working in Windows 8.1
  • Cannot Parse HTML Data Using Android / JSOUP
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • Java static initializers and reflection
  • apache spark aggregate function using min value
  • Is it possible to post an object from jquery to bottle.py?
  • unknown Exception android
  • Is there any way to bind data to data.frame by some index?
  • Django query for large number of relationships
  • Sorting a 2D array using the second column C++
  • Why is Django giving me: 'first_name' is an invalid keyword argument for this function?
  • Observable and ngFor in Angular 2
  • How can I use `wmic` in a Windows PE script?
  • Unable to use reactive element in my shiny app
  • How to push additional view controllers onto NavigationController but keep the TabBar?