{"action":"created","issue":{"url":"https://api.github.com/repos/FasterXML/jackson-databind/issues/1447","repository_url":"https://api.github.com/repos/FasterXML/jackson-databind","labels_url":"https://api.github.com/repos/FasterXML/jackson-databind/issues/1447/labels{/name}","comments_url":"https://api.github.com/repos/FasterXML/jackson-databind/issues/1447/comments","events_url":"https://api.github.com/repos/FasterXML/jackson-databind/issues/1447/events","html_url":"https://github.com/FasterXML/jackson-databind/issues/1447","id":188486029,"number":1447,"title":"A KeyDeserializer instance defined as private static not found even though added to registered SimpleModule","user":{"login":"PawelJagus","id":2006894,"avatar_url":"https://avatars.githubusercontent.com/u/2006894?v=3","gravatar_id":"","url":"https://api.github.com/users/PawelJagus","html_url":"https://github.com/PawelJagus","followers_url":"https://api.github.com/users/PawelJagus/followers","following_url":"https://api.github.com/users/PawelJagus/following{/other_user}","gists_url":"https://api.github.com/users/PawelJagus/gists{/gist_id}","starred_url":"https://api.github.com/users/PawelJagus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PawelJagus/subscriptions","organizations_url":"https://api.github.com/users/PawelJagus/orgs","repos_url":"https://api.github.com/users/PawelJagus/repos","events_url":"https://api.github.com/users/PawelJagus/events{/privacy}","received_events_url":"https://api.github.com/users/PawelJagus/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":7,"created_at":"2016-11-10T11:37:49Z","updated_at":"2016-11-11T06:37:33Z","closed_at":null,"body":"## Matchday.java ##\r\n\r\n    package com.example;\r\n\r\n    import java.io.Serializable;\r\n    import java.util.Objects;\r\n\r\n    public class Matchday implements Serializable, Comparable<Matchday> {\r\n        private static final long serialVersionUID = -8823049187525703664L;\r\n\r\n        private final int matchdayNumber;\r\n\r\n        public Matchday(final int matchdayNumber) {\r\n            this.matchdayNumber = matchdayNumber;\r\n        }\r\n\r\n        public int getMatchdayNumber() {\r\n            return matchdayNumber;\r\n        }\r\n\r\n        @Override\r\n        public int compareTo(Matchday o) {\r\n            return Integer.compare(matchdayNumber, o.getMatchdayNumber());\r\n        }\r\n\r\n        @Override\r\n        public final int hashCode() {\r\n            return Objects.hash(matchdayNumber);\r\n        }\r\n\r\n        @Override\r\n        public final boolean equals(final Object obj) {\r\n            return obj instanceof Matchday && Integer.valueOf(matchdayNumber).equals(((Matchday) obj).matchdayNumber);\r\n        }\r\n        \r\n        @Override\r\n        public String toString() {\r\n            return Integer.toString(matchdayNumber);\r\n        }\r\n    }\r\n\r\n## TeamPlayer.java ##\r\n\r\n    package com.example;\r\n\r\n    import java.io.Serializable;\r\n\r\n    import org.apache.commons.lang3.builder.ToStringBuilder;\r\n\r\n    public class TeamPlayer implements Serializable {\r\n        private static final long serialVersionUID = -6057852081020631549L;\r\n\r\n        private int id;\r\n        private String name;\r\n        private String surname;\r\n\r\n        public int getId() {\r\n            return id;\r\n        }\r\n\r\n        public void setId(int id) {\r\n            this.id = id;\r\n        }\r\n\r\n        public String getName() {\r\n            return name;\r\n        }\r\n\r\n        public void setName(String name) {\r\n            this.name = name;\r\n        }\r\n\r\n        public String getSurname() {\r\n            return surname;\r\n        }\r\n\r\n        public void setSurname(String surname) {\r\n            this.surname = surname;\r\n        }\r\n\r\n        @Override\r\n        public String toString() {\r\n            return new ToStringBuilder(this).append(\"id\", id).append(\"name\", name).append(\"surname\", surname).build()\r\n                    .toString();\r\n        }\r\n    }\r\n\r\n## KeyDeserializerStaticTest.java (Probable Bug in Jackson) ##\r\n\r\n    package com.example;\r\n\r\n    import java.io.ByteArrayInputStream;\r\n    import java.io.IOException;\r\n    import java.io.InputStream;\r\n    import java.util.List;\r\n    import java.util.SortedMap;\r\n\r\n    import com.fasterxml.jackson.core.JsonProcessingException;\r\n    import com.fasterxml.jackson.core.Version;\r\n    import com.fasterxml.jackson.core.type.TypeReference;\r\n    import com.fasterxml.jackson.databind.DeserializationContext;\r\n    import com.fasterxml.jackson.databind.KeyDeserializer;\r\n    import com.fasterxml.jackson.databind.Module;\r\n    import com.fasterxml.jackson.databind.ObjectMapper;\r\n    import com.fasterxml.jackson.databind.module.SimpleModule;\r\n\r\n    public class KeyDeserializerStaticTest {\r\n        public static final ObjectMapper OBJECT_MAPPER = createObjectMapper();\r\n\r\n        private static final KeyDeserializer MATCHDAY_KEY_DESERIALIZER = new KeyDeserializer() {\r\n\r\n            @Override\r\n            public Object deserializeKey(String key, DeserializationContext ctxt)\r\n                    throws IOException, JsonProcessingException {\r\n                return new Matchday(Integer.valueOf(key));\r\n            }\r\n        };\r\n\r\n        private static ObjectMapper createObjectMapper() {\r\n            ObjectMapper objectMapper = new ObjectMapper();\r\n            objectMapper.registerModule(createSimpleModule());\r\n            return objectMapper;\r\n        }\r\n\r\n        private static Module createSimpleModule() {\r\n            SimpleModule simpleModule = new SimpleModule(\"dummy\", new Version(0, 0, 0, \"dummy\", \"dummy\", \"dummy\"));\r\n            simpleModule.addKeyDeserializer(Matchday.class, MATCHDAY_KEY_DESERIALIZER);\r\n            return simpleModule;\r\n        }\r\n\r\n        public static void main(String[] args) throws IOException {\r\n            final InputStream inputStream = new ByteArrayInputStream(\r\n                    \"{\\\"1\\\":[{\\\"id\\\": 1, \\\"name\\\": \\\"Arkadiusz\\\", \\\"surname\\\": \\\"Malarz\\\"}]}\".getBytes());\r\n            SortedMap<Matchday, List<TeamPlayer>> map = OBJECT_MAPPER.readValue(inputStream,\r\n                    new TypeReference<SortedMap<Matchday, List<TeamPlayer>>>() {\r\n                    });\r\n            System.out.println(map);\r\n        }\r\n    }\r\n\r\nThe main method of KeyDeserializerStaticTest ends unexpectedly with this runtime exception.\r\n\r\n    Exception in thread \"main\" com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class com.example.Matchday]\r\n     at [Source: java.io.ByteArrayInputStream@bbc1e0; line: 1, column: 1]\r\n        at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270)\r\n        at com.fasterxml.jackson.databind.DeserializationContext.reportMappingException(DeserializationContext.java:1234)\r\n        at com.fasterxml.jackson.databind.deser.DeserializerCache._handleUnknownKeyDeserializer(DeserializerCache.java:585)\r\n        at com.fasterxml.jackson.databind.deser.DeserializerCache.findKeyDeserializer(DeserializerCache.java:168)\r\n        at com.fasterxml.jackson.databind.DeserializationContext.findKeyDeserializer(DeserializationContext.java:499)\r\n        at com.fasterxml.jackson.databind.deser.std.MapDeserializer.createContextual(MapDeserializer.java:247)\r\n        at com.fasterxml.jackson.databind.DeserializationContext.handleSecondaryContextualization(DeserializationContext.java:681)\r\n        at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:481)\r\n        at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3899)\r\n        at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3794)\r\n        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2915)\r\n        at com.example.KeyDeserializerStaticTest.main(KeyDeserializerStaticTest.java:43)\r\n\r\nBut if I define the custom map key deserializer a bit different semantically, then everything works as expected. It looks like for unknown reason, a map key deserializer instance defined as private static is not visible even if the module it is assigned to is registered.\r\n\r\n## KeyDeserializerTest.java (OK) ## \r\n\r\n    package com.example;\r\n\r\n    import java.io.ByteArrayInputStream;\r\n    import java.io.IOException;\r\n    import java.io.InputStream;\r\n    import java.util.List;\r\n    import java.util.SortedMap;\r\n\r\n    import com.fasterxml.jackson.core.JsonProcessingException;\r\n    import com.fasterxml.jackson.core.Version;\r\n    import com.fasterxml.jackson.core.type.TypeReference;\r\n    import com.fasterxml.jackson.databind.DeserializationContext;\r\n    import com.fasterxml.jackson.databind.KeyDeserializer;\r\n    import com.fasterxml.jackson.databind.ObjectMapper;\r\n    import com.fasterxml.jackson.databind.module.SimpleModule;\r\n\r\n    public class KeyDeserializerTest {\r\n\r\n        public static void main(String[] args) throws IOException {\r\n            final ObjectMapper objectMapper = new ObjectMapper();\r\n            final SimpleModule mySimpleModule = new SimpleModule(\"dummy\", new Version(0, 0, 0, \"dummy\", \"dummy\", \"dummy\"));\r\n            mySimpleModule.addKeyDeserializer(Matchday.class, new KeyDeserializer() {\r\n\r\n                @Override\r\n                public Object deserializeKey(String arg0, DeserializationContext arg1)\r\n                        throws IOException, JsonProcessingException {\r\n                    return new Matchday(Integer.valueOf(arg0));\r\n                }\r\n            });\r\n            objectMapper.registerModule(mySimpleModule);\r\n\r\n            final InputStream inputStream = new ByteArrayInputStream(\r\n                    \"{\\\"1\\\":[{\\\"id\\\": 1, \\\"name\\\": \\\"Arkadiusz\\\", \\\"surname\\\": \\\"Malarz\\\"}]}\".getBytes());\r\n            SortedMap<Matchday, List<TeamPlayer>> map = objectMapper.readValue(inputStream,\r\n                    new TypeReference<SortedMap<Matchday, List<TeamPlayer>>>() {\r\n                    });\r\n            System.out.println(map);\r\n        }\r\n\r\n    }"},"comment":{"url":"https://api.github.com/repos/FasterXML/jackson-databind/issues/comments/259891778","html_url":"https://github.com/FasterXML/jackson-databind/issues/1447#issuecomment-259891778","issue_url":"https://api.github.com/repos/FasterXML/jackson-databind/issues/1447","id":259891778,"user":{"login":"cowtowncoder","id":55065,"avatar_url":"https://avatars.githubusercontent.com/u/55065?v=3","gravatar_id":"","url":"https://api.github.com/users/cowtowncoder","html_url":"https://github.com/cowtowncoder","followers_url":"https://api.github.com/users/cowtowncoder/followers","following_url":"https://api.github.com/users/cowtowncoder/following{/other_user}","gists_url":"https://api.github.com/users/cowtowncoder/gists{/gist_id}","starred_url":"https://api.github.com/users/cowtowncoder/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cowtowncoder/subscriptions","organizations_url":"https://api.github.com/users/cowtowncoder/orgs","repos_url":"https://api.github.com/users/cowtowncoder/repos","events_url":"https://api.github.com/users/cowtowncoder/events{/privacy}","received_events_url":"https://api.github.com/users/cowtowncoder/received_events","type":"User","site_admin":false},"created_at":"2016-11-11T06:37:33Z","updated_at":"2016-11-11T06:37:33Z","body":"Wow. This is interesting... it comes down to having two tests. Almost as if caching was failing..."}}
{"actor":{"display_login":"cowtowncoder"}}