Skip to content

Commit

Permalink
Fixed #67
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Jul 4, 2020
1 parent 902fa38 commit c3cd1dc
Show file tree
Hide file tree
Showing 17 changed files with 163 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -73,7 +79,6 @@ protected T _deserializeContents(JsonParser p, DeserializationContext ctxt)
}

/**
*
* @since 2.10
*/
protected Object _resolveNullToValue(DeserializationContext ctxt) throws IOException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<T extends ImmutableMap<Object, Object>> extends
Expand All @@ -26,6 +26,12 @@ abstract class GuavaImmutableMapDeserializer<T extends ImmutableMap<Object, Obje
super(type, keyDeser, valueDeser, valueTypeDeser, nuller);
}

@Override
public AccessPattern getEmptyAccessPattern() {
// immutable, hence:
return AccessPattern.CONSTANT;
}

protected abstract ImmutableMap.Builder<Object, Object> createBuilder();

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>
extends ContainerDeserializerBase<T>
Expand Down Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
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;
import com.fasterxml.jackson.databind.JavaType;
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<T extends Multiset<Object>>
Expand All @@ -27,9 +26,21 @@ abstract class GuavaMultisetDeserializer<T extends Multiset<Object>>

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;
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<Object, Object> createBuilder() {
return ImmutableBiMap.builder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<ImmutableList<Object>>
GuavaImmutableCollectionDeserializer<ImmutableList<Object>>
{
private static final long serialVersionUID = 1L;

Expand Down Expand Up @@ -38,12 +36,12 @@ protected ImmutableList.Builder<Object> createBuilder() {
}

@Override
protected ImmutableList<Object> _createEmpty(DeserializationContext ctxt) throws IOException {
protected ImmutableList<Object> _createEmpty(DeserializationContext ctxt) {
return ImmutableList.of();
}

@Override
protected ImmutableList<Object> _createWithSingleElement(DeserializationContext ctxt, Object value) throws IOException {
protected ImmutableList<Object> _createWithSingleElement(DeserializationContext ctxt, Object value) {
return ImmutableList.of(value);
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ public GuavaCollectionDeserializer<ImmutableMultiset<Object>> withResolved(JsonD
}

@Override
protected ImmutableMultiset<Object> _createEmpty(DeserializationContext ctxt) throws IOException {
protected ImmutableMultiset<Object> _createEmpty(DeserializationContext ctxt) {
return ImmutableMultiset.of();
}

@Override
protected ImmutableMultiset<Object> _createWithSingleElement(DeserializationContext ctxt, Object value) throws IOException {
protected ImmutableMultiset<Object> _createWithSingleElement(DeserializationContext ctxt, Object value) {
return ImmutableMultiset.of(value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ protected Builder<Object> createBuilder() {
}

@Override
protected ImmutableSet<Object> _createEmpty(DeserializationContext ctxt) throws IOException {
protected ImmutableSet<Object> _createEmpty(DeserializationContext ctxt) {
return ImmutableSet.of();
}

@Override
protected ImmutableSet<Object> _createWithSingleElement(DeserializationContext ctxt, Object value) throws IOException {
protected ImmutableSet<Object> _createWithSingleElement(DeserializationContext ctxt, Object value) {
return ImmutableSet.of(value);
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<Object, Object> createBuilder() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ protected Builder<Object> createBuilder() {
}

@Override
protected ImmutableSortedMultiset<Object> _createEmpty(DeserializationContext ctxt) throws IOException {
protected ImmutableSortedMultiset<Object> _createEmpty(DeserializationContext ctxt) {
return ImmutableSortedMultiset.of();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ protected Builder<Object> createBuilder() {
}

@Override
protected ImmutableSortedSet<Object> _createEmpty(DeserializationContext ctxt) throws IOException {
protected ImmutableSortedSet<Object> _createEmpty(DeserializationContext ctxt) {
return ImmutableSortedSet.of();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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<ImmutableList<String>> lists = ImmutableList.of();
}

public static class ImmutableMapContainer67 {
public ImmutableMap<String, ImmutableMap<String, String>> 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());
}
}
Loading

0 comments on commit c3cd1dc

Please sign in to comment.