diff --git a/CHANGELOG.md b/CHANGELOG.md index f34999c8..5752802e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,13 @@ CHANGELOG ========= +3.1.1 +------------------ + +* When handling a deserialization exception, the decoder now avoids + throwing a `NullPointerException` when one of the constructor arguments + is `null`. Reported by Keith Massey. GitHub #164. + 3.1.0 (2023-12-05) ------------------ diff --git a/src/main/java/com/maxmind/db/Decoder.java b/src/main/java/com/maxmind/db/Decoder.java index 23518adf..ab1bc5e2 100644 --- a/src/main/java/com/maxmind/db/Decoder.java +++ b/src/main/java/com/maxmind/db/Decoder.java @@ -447,7 +447,8 @@ private Object decodeMapIntoObject(int size, Class cls) StringBuilder sbErrors = new StringBuilder(); for (String key : parameterIndexes.keySet()) { int index = parameterIndexes.get(key); - if (!parameters[index].getClass().isAssignableFrom(parameterTypes[index])) { + if (parameters[index] != null + && !parameters[index].getClass().isAssignableFrom(parameterTypes[index])) { sbErrors.append(" argument type mismatch in " + key + " MMDB Type: " + parameters[index].getClass().getCanonicalName() + " Java Type: " + parameterTypes[index].getCanonicalName()); diff --git a/src/test/java/com/maxmind/db/ReaderTest.java b/src/test/java/com/maxmind/db/ReaderTest.java index 0f4d09b9..004ecb24 100644 --- a/src/test/java/com/maxmind/db/ReaderTest.java +++ b/src/test/java/com/maxmind/db/ReaderTest.java @@ -944,6 +944,31 @@ public void testDecodeWithDataTypeMismatchInModel() throws IOException { assertThat(ex.getCause().getCause().getClass(), equalTo(ClassCastException.class)); } + + static class TestConstructorMismatchModel { + @MaxMindDbConstructor + public TestConstructorMismatchModel( + @MaxMindDbParameter(name = "other") + String other, + @MaxMindDbParameter(name = "utf8_string") + double utf8StringField + ) { + } + } + + @Test + public void testDecodeWithDataTypeMismatchInModelAndNullValue() throws IOException { + this.testReader = new Reader(getFile("MaxMind-DB-test-decoder.mmdb")); + + DeserializationException ex = assertThrows(DeserializationException.class, + () -> this.testReader.get( + InetAddress.getByName("::1.1.1.0"), + TestConstructorMismatchModel.class)); + + assertThat(ex.getMessage(), containsString("Error creating object of type")); + assertThat(ex.getCause().getCause().getClass(), equalTo(IllegalArgumentException.class)); + } + static class TestWrongModelSubdivisions { List subdivisions;