From c3cd1dcb94c060dd5acf738960ac0db330bc8158 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Sat, 4 Jul 2020 15:01:07 -0700 Subject: [PATCH] Fixed #67 --- .../deser/GuavaCollectionDeserializer.java | 12 +++- .../GuavaImmutableCollectionDeserializer.java | 7 +- .../deser/GuavaImmutableMapDeserializer.java | 8 ++- .../guava/deser/GuavaMapDeserializer.java | 9 +++ .../deser/GuavaMultisetDeserializer.java | 21 ++++-- .../guava/deser/HashMultisetDeserializer.java | 2 + .../deser/ImmutableBiMapDeserializer.java | 7 ++ .../deser/ImmutableListDeserializer.java | 8 +-- .../guava/deser/ImmutableMapDeserializer.java | 7 ++ .../deser/ImmutableMultisetDeserializer.java | 4 +- .../guava/deser/ImmutableSetDeserializer.java | 4 +- .../deser/ImmutableSortedMapDeserializer.java | 7 ++ .../ImmutableSortedMultisetDeserializer.java | 2 +- .../deser/ImmutableSortedSetDeserializer.java | 2 +- .../datatype/guava/EmptyCollectionsTest.java | 72 +++++++++++++++++++ .../datatype/guava/ModuleTestBase.java | 6 +- release-notes/VERSION-2.x | 5 ++ 17 files changed, 163 insertions(+), 20 deletions(-) create mode 100644 guava/src/test/java/com/fasterxml/jackson/datatype/guava/EmptyCollectionsTest.java diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaCollectionDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaCollectionDeserializer.java index 12f73630..0184a578 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaCollectionDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaCollectionDeserializer.java @@ -10,6 +10,7 @@ import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; +import com.fasterxml.jackson.databind.util.AccessPattern; /** * Base class for Guava-specific collection deserializers. @@ -141,6 +142,14 @@ public T deserialize(JsonParser p, DeserializationContext ctxt) /********************************************************************** */ + // Force abstract-ness for subclasses + @Override + public abstract AccessPattern getEmptyAccessPattern(); + + // Force abstract-ness for subclasses + @Override + public abstract Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException; + protected abstract T _deserializeContents(JsonParser p, DeserializationContext ctxt) throws IOException; @@ -173,7 +182,8 @@ protected T _deserializeFromSingleValue(JsonParser p, DeserializationContext ctx } - protected abstract T _createEmpty(DeserializationContext ctxt) throws IOException; + // Note: 'throws IOException' dropped from 2.10.5 + protected abstract T _createEmpty(DeserializationContext ctxt); protected abstract T _createWithSingleElement(DeserializationContext ctxt, Object value) throws IOException; } diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaImmutableCollectionDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaImmutableCollectionDeserializer.java index cd98d660..ab2483f8 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaImmutableCollectionDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaImmutableCollectionDeserializer.java @@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.util.AccessPattern; @@ -39,6 +40,11 @@ public AccessPattern getEmptyAccessPattern() { return AccessPattern.CONSTANT; } + @Override + public T getEmptyValue(DeserializationContext ctxt) { + return _createEmpty(ctxt); + } + @Override protected T _deserializeContents(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException @@ -73,7 +79,6 @@ protected T _deserializeContents(JsonParser p, DeserializationContext ctxt) } /** - * * @since 2.10 */ protected Object _resolveNullToValue(DeserializationContext ctxt) throws IOException diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaImmutableMapDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaImmutableMapDeserializer.java index 74f2d31f..3aad0d6c 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaImmutableMapDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaImmutableMapDeserializer.java @@ -12,7 +12,7 @@ import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; - +import com.fasterxml.jackson.databind.util.AccessPattern; import com.google.common.collect.ImmutableMap; abstract class GuavaImmutableMapDeserializer> extends @@ -26,6 +26,12 @@ abstract class GuavaImmutableMapDeserializer createBuilder(); @Override diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaMapDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaMapDeserializer.java index 24b9883e..d3293032 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaMapDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaMapDeserializer.java @@ -10,6 +10,7 @@ import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; +import com.fasterxml.jackson.databind.util.AccessPattern; public abstract class GuavaMapDeserializer extends ContainerDeserializerBase @@ -166,6 +167,14 @@ public T deserialize(JsonParser p, DeserializationContext ctxt) /********************************************************************** */ + // Force abstract-ness for subclasses + @Override + public abstract AccessPattern getEmptyAccessPattern(); + + // Force abstract-ness for subclasses + @Override + public abstract Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException; + protected abstract T _deserializeEntries(JsonParser p, DeserializationContext ctxt) throws IOException; } diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaMultisetDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaMultisetDeserializer.java index a81118ad..c428a7e2 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaMultisetDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/GuavaMultisetDeserializer.java @@ -3,7 +3,6 @@ import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; @@ -11,7 +10,7 @@ import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; - +import com.fasterxml.jackson.databind.util.AccessPattern; import com.google.common.collect.Multiset; abstract class GuavaMultisetDeserializer> @@ -27,9 +26,21 @@ abstract class GuavaMultisetDeserializer> protected abstract T createMultiset(); + @Override + public AccessPattern getEmptyAccessPattern() { + // mutable, hence must be: + return AccessPattern.DYNAMIC; + } + + @Override + public T getEmptyValue(DeserializationContext ctxt) { + return _createEmpty(ctxt); + } + @Override protected T _deserializeContents(JsonParser p, DeserializationContext ctxt) throws IOException, - JsonProcessingException { + IOException + { JsonDeserializer valueDes = _valueDeserializer; JsonToken t; final TypeDeserializer typeDeser = _valueTypeDeserializer; @@ -54,12 +65,12 @@ protected T _deserializeContents(JsonParser p, DeserializationContext ctxt) thro } @Override - protected T _createEmpty(DeserializationContext ctxt) throws IOException { + protected T _createEmpty(DeserializationContext ctxt) { return createMultiset(); } @Override - protected T _createWithSingleElement(DeserializationContext ctxt, Object value) throws IOException { + protected T _createWithSingleElement(DeserializationContext ctxt, Object value) { final T result = createMultiset(); result.add(value); return result; diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/HashMultisetDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/HashMultisetDeserializer.java index f6b44a5b..31df3eb5 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/HashMultisetDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/HashMultisetDeserializer.java @@ -1,8 +1,10 @@ package com.fasterxml.jackson.datatype.guava.deser; +import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableBiMapDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableBiMapDeserializer.java index f2cd17c6..1b51b235 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableBiMapDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableBiMapDeserializer.java @@ -1,7 +1,9 @@ package com.fasterxml.jackson.datatype.guava.deser; +import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; @@ -20,6 +22,11 @@ public ImmutableBiMapDeserializer(JavaType type, KeyDeserializer keyDeser, super(type, keyDeser, deser, typeDeser, nuller); } + @Override + public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { + return ImmutableBiMap.of(); + } + @Override protected Builder createBuilder() { return ImmutableBiMap.builder(); diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableListDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableListDeserializer.java index 1394b337..1e8cafb5 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableListDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableListDeserializer.java @@ -2,14 +2,12 @@ import com.google.common.collect.ImmutableList; -import java.io.IOException; - import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; public class ImmutableListDeserializer extends - GuavaImmutableCollectionDeserializer> + GuavaImmutableCollectionDeserializer> { private static final long serialVersionUID = 1L; @@ -38,12 +36,12 @@ protected ImmutableList.Builder createBuilder() { } @Override - protected ImmutableList _createEmpty(DeserializationContext ctxt) throws IOException { + protected ImmutableList _createEmpty(DeserializationContext ctxt) { return ImmutableList.of(); } @Override - protected ImmutableList _createWithSingleElement(DeserializationContext ctxt, Object value) throws IOException { + protected ImmutableList _createWithSingleElement(DeserializationContext ctxt, Object value) { return ImmutableList.of(value); } } diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableMapDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableMapDeserializer.java index e8daa7e9..90237ce6 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableMapDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableMapDeserializer.java @@ -1,7 +1,9 @@ package com.fasterxml.jackson.datatype.guava.deser; +import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; @@ -20,6 +22,11 @@ public ImmutableMapDeserializer(JavaType type, KeyDeserializer keyDeser, super(type, keyDeser, valueDeser, valueTypeDeser, nuller); } + @Override + public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { + return ImmutableMap.of(); + } + @Override public ImmutableMapDeserializer withResolved(KeyDeserializer keyDeser, JsonDeserializer valueDeser, TypeDeserializer valueTypeDeser, diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableMultisetDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableMultisetDeserializer.java index d4236803..5309c287 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableMultisetDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableMultisetDeserializer.java @@ -34,12 +34,12 @@ public GuavaCollectionDeserializer> withResolved(JsonD } @Override - protected ImmutableMultiset _createEmpty(DeserializationContext ctxt) throws IOException { + protected ImmutableMultiset _createEmpty(DeserializationContext ctxt) { return ImmutableMultiset.of(); } @Override - protected ImmutableMultiset _createWithSingleElement(DeserializationContext ctxt, Object value) throws IOException { + protected ImmutableMultiset _createWithSingleElement(DeserializationContext ctxt, Object value) { return ImmutableMultiset.of(value); } } diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSetDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSetDeserializer.java index d2134546..ed3ffb14 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSetDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSetDeserializer.java @@ -34,12 +34,12 @@ protected Builder createBuilder() { } @Override - protected ImmutableSet _createEmpty(DeserializationContext ctxt) throws IOException { + protected ImmutableSet _createEmpty(DeserializationContext ctxt) { return ImmutableSet.of(); } @Override - protected ImmutableSet _createWithSingleElement(DeserializationContext ctxt, Object value) throws IOException { + protected ImmutableSet _createWithSingleElement(DeserializationContext ctxt, Object value) { return ImmutableSet.of(value); } } diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSortedMapDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSortedMapDeserializer.java index 43f88f33..5549424e 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSortedMapDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSortedMapDeserializer.java @@ -1,7 +1,9 @@ package com.fasterxml.jackson.datatype.guava.deser; +import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.KeyDeserializer; import com.fasterxml.jackson.databind.deser.NullValueProvider; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; @@ -20,6 +22,11 @@ public ImmutableSortedMapDeserializer(JavaType type, KeyDeserializer keyDeser, super(type, keyDeser, valueDeser, typeDeser, nuller); } + @Override + public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException { + return ImmutableSortedMap.of(); + } + @SuppressWarnings("unchecked") @Override protected Builder createBuilder() { diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSortedMultisetDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSortedMultisetDeserializer.java index 9bfec14b..8d31e77a 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSortedMultisetDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSortedMultisetDeserializer.java @@ -37,7 +37,7 @@ protected Builder createBuilder() { } @Override - protected ImmutableSortedMultiset _createEmpty(DeserializationContext ctxt) throws IOException { + protected ImmutableSortedMultiset _createEmpty(DeserializationContext ctxt) { return ImmutableSortedMultiset.of(); } diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSortedSetDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSortedSetDeserializer.java index 715ac0de..0f8eb6f1 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSortedSetDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/ImmutableSortedSetDeserializer.java @@ -43,7 +43,7 @@ protected Builder createBuilder() { } @Override - protected ImmutableSortedSet _createEmpty(DeserializationContext ctxt) throws IOException { + protected ImmutableSortedSet _createEmpty(DeserializationContext ctxt) { return ImmutableSortedSet.of(); } diff --git a/guava/src/test/java/com/fasterxml/jackson/datatype/guava/EmptyCollectionsTest.java b/guava/src/test/java/com/fasterxml/jackson/datatype/guava/EmptyCollectionsTest.java new file mode 100644 index 00000000..533fe755 --- /dev/null +++ b/guava/src/test/java/com/fasterxml/jackson/datatype/guava/EmptyCollectionsTest.java @@ -0,0 +1,72 @@ +package com.fasterxml.jackson.datatype.guava; + +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +public class EmptyCollectionsTest extends ModuleTestBase +{ + // [datatypes-collections#67] + public static class ImmutableListContainer67 { + public ImmutableList> lists = ImmutableList.of(); + } + + public static class ImmutableMapContainer67 { + public ImmutableMap> maps = ImmutableMap.of(); + } + + private final ObjectMapper EMPTY_MAPPER = builderWithModule() + .defaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY) + .withValueNulls(Nulls.AS_EMPTY)) + .build(); + + // [datatypes-collections#67] + public void testEmptyForLists() throws Exception + { + ImmutableListContainer67 result; + + // First, value `null` into empty: + result = EMPTY_MAPPER.readValue(a2q("{'lists':null}"), ImmutableListContainer67.class); + assertNotNull(result.lists); + assertEquals(0, result.lists.size()); + + // then content null: + result = EMPTY_MAPPER.readValue(a2q("{'lists':[ null ]}"), ImmutableListContainer67.class); + assertNotNull(result.lists); + assertEquals(1, result.lists.size()); + assertNotNull(result.lists.get(0)); + assertEquals(0, result.lists.get(0).size()); + + // and finally round-trip too + String json = EMPTY_MAPPER.writeValueAsString(new ImmutableListContainer67()); + result = EMPTY_MAPPER.readValue(json, ImmutableListContainer67.class); + assertNotNull(result.lists); + assertEquals(0, result.lists.size()); + } + + public void testEmptyForMaps() throws Exception + { + ImmutableMapContainer67 result; + + // First, value `null` into empty: + result = EMPTY_MAPPER.readValue(a2q("{'maps':null}"), ImmutableMapContainer67.class); + assertNotNull(result.maps); + assertEquals(0, result.maps.size()); + + // then content null: + result = EMPTY_MAPPER.readValue(a2q("{'maps':{ 'key' : null }}"), ImmutableMapContainer67.class); + assertNotNull(result.maps); + assertEquals(1, result.maps.size()); + assertNotNull(result.maps.get("key")); + assertEquals(0, result.maps.get("key").size()); + + // and finally round-trip too + String json = EMPTY_MAPPER.writeValueAsString(new ImmutableMapContainer67()); + result = EMPTY_MAPPER.readValue(json, ImmutableMapContainer67.class); + assertNotNull(result.maps); + assertEquals(0, result.maps.size()); + } +} diff --git a/guava/src/test/java/com/fasterxml/jackson/datatype/guava/ModuleTestBase.java b/guava/src/test/java/com/fasterxml/jackson/datatype/guava/ModuleTestBase.java index bc8bf417..81d75277 100644 --- a/guava/src/test/java/com/fasterxml/jackson/datatype/guava/ModuleTestBase.java +++ b/guava/src/test/java/com/fasterxml/jackson/datatype/guava/ModuleTestBase.java @@ -26,7 +26,7 @@ protected ObjectMapper mapperWithModule(boolean absentsAsNulls) protected JsonMapper.Builder builderWithModule() { return builderWithModule(false); } - + protected JsonMapper.Builder builderWithModule(boolean absentsAsNulls) { GuavaModule module = new GuavaModule(); module.configureAbsentsAsNulls(absentsAsNulls); @@ -34,6 +34,10 @@ protected JsonMapper.Builder builderWithModule(boolean absentsAsNulls) { .addModule(module); } + protected String a2q(String json) { + return aposToQuotes(json); + } + protected String aposToQuotes(String json) { return json.replace("'", "\""); } diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index a48d4d2f..745d9a95 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -9,6 +9,11 @@ Modules: === Releases === ------------------------------------------------------------------------ +2.10.5 (not yet released) + +#67: Guava collection deserialization failure with `Nulls.AS_EMPTY` + (reported by ari-talja-rovio@github) + 2.10.4 (03-May-2020) 2.10.3 (03-Mar-2020) 2.10.2 (05-Jan-2020)