From e115085b14fbcaeca8445b545c8ee948d28a9cad Mon Sep 17 00:00:00 2001 From: Brian Demers Date: Mon, 24 Feb 2020 13:42:02 -0500 Subject: [PATCH] Allow JacksonDeserializer to work with Java 9+ Map.of and other maps that do NOT allow null keys --- CHANGELOG.md | 6 ++++ .../jackson/io/JacksonDeserializer.java | 5 +-- .../jackson/io/JacksonDeserializerTest.groovy | 35 +++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa4896ac..7107a7ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## Release Notes +### 0.11.1 + +This patch release: + +* Fixes issue when using Java 9+ `Map.of` with JacksonDeserializer which resulted in an NullPointerException + ### 0.11.0 This minor release: diff --git a/extensions/jackson/src/main/java/io/jsonwebtoken/jackson/io/JacksonDeserializer.java b/extensions/jackson/src/main/java/io/jsonwebtoken/jackson/io/JacksonDeserializer.java index b0130a22..a9ea111e 100644 --- a/extensions/jackson/src/main/java/io/jsonwebtoken/jackson/io/JacksonDeserializer.java +++ b/extensions/jackson/src/main/java/io/jsonwebtoken/jackson/io/JacksonDeserializer.java @@ -120,8 +120,9 @@ public class JacksonDeserializer implements Deserializer { @Override public Object deserialize(JsonParser parser, DeserializationContext context) throws IOException { // check if the current claim key is mapped, if so traverse it's value - if (claimTypeMap != null && claimTypeMap.containsKey(parser.currentName())) { - Class type = claimTypeMap.get(parser.currentName()); + String name = parser.currentName(); + if (claimTypeMap != null && name != null && claimTypeMap.containsKey(name)) { + Class type = claimTypeMap.get(name); return parser.readValueAsTree().traverse(parser.getCodec()).readValueAs(type); } // otherwise default to super diff --git a/extensions/jackson/src/test/groovy/io/jsonwebtoken/jackson/io/JacksonDeserializerTest.groovy b/extensions/jackson/src/test/groovy/io/jsonwebtoken/jackson/io/JacksonDeserializerTest.groovy index ca77e741..7dd3799d 100644 --- a/extensions/jackson/src/test/groovy/io/jsonwebtoken/jackson/io/JacksonDeserializerTest.groovy +++ b/extensions/jackson/src/test/groovy/io/jsonwebtoken/jackson/io/JacksonDeserializerTest.groovy @@ -105,6 +105,41 @@ class JacksonDeserializerTest { assertEquals expected, result } + /** + * For: https://github.com/jwtk/jjwt/issues/564 + */ + @Test + void testMappedTypeDeserializerWithMapNullCheck() { + + // mimic map implementations that do NOT allow for null keys, or containsKey(null) + Map typeMap = new HashMap() { + @Override + boolean containsKey(Object key) { + if (key == null) { + throw new NullPointerException("key is null, expected for this test") + } + return super.containsKey(key) + } + } + + // TODO: the following does NOT work with Java 1.7 + // when we stop supporting that version we can use a partial mock instead + // the `typeMap.put("custom", CustomBean)` line below results in an NPE, (only on 1.7) + +// Map typeMap = partialMockBuilder(HashMap) +// .addMockedMethod("containsKey") +// .createNiceMock() +// +// expect(typeMap.containsKey(null)).andThrow(new NullPointerException("key is null, expected for this test")) +// replay(typeMap) + + typeMap.put("custom", CustomBean) + + def deserializer = new JacksonDeserializer(typeMap) + def result = deserializer.deserialize('{"alg":"HS256"}'.getBytes("UTF-8")) + assertEquals(["alg": "HS256"], result) + } + @Test(expected = IllegalArgumentException) void testNullClaimTypeMap() { new JacksonDeserializer((Map) null)