java - Statically defined KeyDeserializer not found but if defined locally everything perfect -


i baffled how registering custom keydeserializer works.

here code:

matchday.java

package com.example;  import java.io.serializable; import java.util.objects;  public class matchday implements serializable, comparable<matchday> {     private static final long serialversionuid = -8823049187525703664l;      private final int matchdaynumber;      public matchday(final int matchdaynumber) {         this.matchdaynumber = matchdaynumber;     }      public int getmatchdaynumber() {         return matchdaynumber;     }      @override     public int compareto(matchday o) {         return integer.compare(matchdaynumber, o.getmatchdaynumber());     }      @override     public final int hashcode() {         return objects.hash(matchdaynumber);     }      @override     public final boolean equals(final object obj) {         return obj instanceof matchday && integer.valueof(matchdaynumber).equals(((matchday) obj).matchdaynumber);     }      @override     public string tostring() {         return integer.tostring(matchdaynumber);     } } 

teamplayer.java

package com.example;  import java.io.serializable;  import org.apache.commons.lang3.builder.tostringbuilder;  public class teamplayer implements serializable {     private static final long serialversionuid = -6057852081020631549l;      private int id;     private string name;     private string surname;      public int getid() {         return id;     }      public void setid(int id) {         this.id = id;     }      public string getname() {         return name;     }      public void setname(string name) {         this.name = name;     }      public string getsurname() {         return surname;     }      public void setsurname(string surname) {         this.surname = surname;     }      @override     public string tostring() {         return new tostringbuilder(this).append("id", id).append("name", name).append("surname", surname).build()                 .tostring();     } } 

now if define custom map key deserializer class matchday.java, works charm if this.

keydeserializertest.java

package com.example;  import java.io.bytearrayinputstream; import java.io.ioexception; import java.io.inputstream; import java.util.list; import java.util.sortedmap;  import com.fasterxml.jackson.core.jsonprocessingexception; import com.fasterxml.jackson.core.version; import com.fasterxml.jackson.core.type.typereference; import com.fasterxml.jackson.databind.deserializationcontext; import com.fasterxml.jackson.databind.keydeserializer; import com.fasterxml.jackson.databind.objectmapper; import com.fasterxml.jackson.databind.module.simplemodule;  public class keydeserializertest {      public static void main(string[] args) throws ioexception {         final objectmapper objectmapper = new objectmapper();         final simplemodule mysimplemodule = new simplemodule("dummy", new version(0, 0, 0, "dummy", "dummy", "dummy"));         mysimplemodule.addkeydeserializer(matchday.class, new keydeserializer() {              @override             public object deserializekey(string arg0, deserializationcontext arg1)                     throws ioexception, jsonprocessingexception {                 return new matchday(integer.valueof(arg0));             }         });         objectmapper.registermodule(mysimplemodule);          final inputstream inputstream = new bytearrayinputstream(                 "{\"1\":[{\"id\": 1, \"name\": \"arkadiusz\", \"surname\": \"malarz\"}]}".getbytes());         sortedmap<matchday, list<teamplayer>> map = objectmapper.readvalue(inputstream,                 new typereference<sortedmap<matchday, list<teamplayer>>>() {                 });         system.out.println(map);     }  } 

it prints

{1=[com.example.teamplayer@3a8624[id=1,name=arkadiusz,surname=malarz]]} 

but if define both object mapper , deserializer instances static attributes following exception!

keydeserializerstatictest.java

package com.example;  import java.io.bytearrayinputstream; import java.io.ioexception; import java.io.inputstream; import java.util.list; import java.util.sortedmap;  import com.fasterxml.jackson.core.jsonprocessingexception; import com.fasterxml.jackson.core.version; import com.fasterxml.jackson.core.type.typereference; import com.fasterxml.jackson.databind.deserializationcontext; import com.fasterxml.jackson.databind.keydeserializer; import com.fasterxml.jackson.databind.module; import com.fasterxml.jackson.databind.objectmapper; import com.fasterxml.jackson.databind.module.simplemodule;  public class keydeserializerstatictest {     public static final objectmapper object_mapper = createobjectmapper();      private static final keydeserializer matchday_key_deserializer = new keydeserializer() {          @override         public object deserializekey(string key, deserializationcontext ctxt)                 throws ioexception, jsonprocessingexception {             return new matchday(integer.valueof(key));         }     };      private static objectmapper createobjectmapper() {         objectmapper objectmapper = new objectmapper();         objectmapper.registermodule(createsimplemodule());         return objectmapper;     }      private static module createsimplemodule() {         simplemodule simplemodule = new simplemodule("dummy", new version(0, 0, 0, "dummy", "dummy", "dummy"));         simplemodule.addkeydeserializer(matchday.class, matchday_key_deserializer);         return simplemodule;     }      public static void main(string[] args) throws ioexception {         final inputstream inputstream = new bytearrayinputstream(                 "{\"1\":[{\"id\": 1, \"name\": \"arkadiusz\", \"surname\": \"malarz\"}]}".getbytes());         sortedmap<matchday, list<teamplayer>> map = object_mapper.readvalue(inputstream,                 new typereference<sortedmap<matchday, list<teamplayer>>>() {                 });         system.out.println(map);     } } 
exception in thread "main" com.fasterxml.jackson.databind.jsonmappingexception: can not find (map) key deserializer type [simple type, class com.example.matchday]  @ [source: java.io.bytearrayinputstream@bbc1e0; line: 1, column: 1]     @ com.fasterxml.jackson.databind.jsonmappingexception.from(jsonmappingexception.java:270)     @ com.fasterxml.jackson.databind.deserializationcontext.reportmappingexception(deserializationcontext.java:1234)     @ com.fasterxml.jackson.databind.deser.deserializercache._handleunknownkeydeserializer(deserializercache.java:585)     @ com.fasterxml.jackson.databind.deser.deserializercache.findkeydeserializer(deserializercache.java:168)     @ com.fasterxml.jackson.databind.deserializationcontext.findkeydeserializer(deserializationcontext.java:499)     @ com.fasterxml.jackson.databind.deser.std.mapdeserializer.createcontextual(mapdeserializer.java:247)     @ com.fasterxml.jackson.databind.deserializationcontext.handlesecondarycontextualization(deserializationcontext.java:681)     @ com.fasterxml.jackson.databind.deserializationcontext.findrootvaluedeserializer(deserializationcontext.java:481)     @ com.fasterxml.jackson.databind.objectmapper._findrootdeserializer(objectmapper.java:3899)     @ com.fasterxml.jackson.databind.objectmapper._readmapandclose(objectmapper.java:3794)     @ com.fasterxml.jackson.databind.objectmapper.readvalue(objectmapper.java:2915)     @ com.example.keydeserializerstatictest.main(keydeserializerstatictest.java:43) 

what wrong here? semantically there no difference between above presented main methods. feature somewhere documented or bug in jackson?

the root problem here order of initialization of static variables.

it is

public static final objectmapper object_mapper = createobjectmapper();  private static final keydeserializer matchday_key_deserializer = new keydeserializer() {      @override     public object deserializekey(string key, deserializationcontext ctxt)             throws ioexception, jsonprocessingexception {         return new matchday(integer.valueof(key));     } }; 

while should be

private static final keydeserializer matchday_key_deserializer = new keydeserializer() {      @override     public object deserializekey(string key, deserializationcontext ctxt)             throws ioexception, jsonprocessingexception {         return new matchday(integer.valueof(key));     } };  public static final objectmapper object_mapper = createobjectmapper(); 

this hard spot because method addkeydeserializer(class<?>, keydeserializer) of class simplemodule silently adds null references internal key deserializers' map. in opinion should throw nullpointerexception upon trying adding key deserializer reference null.

the jackson code looks this.

first addkekeydeserializer(class<?>, keydeserializer)

public simplemodule addkeydeserializer(class<?> type, keydeserializer deser) {     if (_keydeserializers == null) {         _keydeserializers = new simplekeydeserializers();     }     _keydeserializers.adddeserializer(type, deser);     return this; } 

there no check here whether deser null.

then delegates adddeserializer(class, keydeserializer) of class simplekeydeserializers.

public simplekeydeserializers adddeserializer(class<?> forclass, keydeserializer deser) {     if (_classmappings == null) {         _classmappings = new hashmap<classkey,keydeserializer>();     }     _classmappings.put(new classkey(forclass), deser);     return this; } 

here null reference ignored , silently put _classmappings map.

here issue posted on github discussion.


Comments

Popular posts from this blog

asynchronous - C# WinSCP .NET assembly: How to upload multiple files asynchronously -

aws api gateway - SerializationException in posting new Records via Dynamodb Proxy Service in API -

asp.net - Problems sending emails from forum -