Skip to content

Commit afdabd3

Browse files
authored
Add support for Guava primitives during deserialization (#69)
Add support for Guava primitives (Booleans.asList(..), Bytes.asList(..), etc)
1 parent c8d2db1 commit afdabd3

14 files changed

+808
-3
lines changed

guava/src/main/java/com/fasterxml/jackson/datatype/guava/GuavaDeserializers.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.fasterxml.jackson.datatype.guava;
22

3+
import com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes;
34
import com.google.common.base.Optional;
45
import com.google.common.collect.*;
56
import com.google.common.hash.HashCode;
@@ -21,6 +22,8 @@
2122

2223
import java.io.Serializable;
2324

25+
import static com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes.isAssignableFromPrimitive;
26+
2427
/**
2528
* Custom deserializers module offers.
2629
*/
@@ -127,7 +130,9 @@ public ValueDeserializer<?> findCollectionDeserializer(CollectionType type,
127130
null, null);
128131
}
129132

130-
return null;
133+
return isAssignableFromPrimitive(raw)
134+
.transform(PrimitiveTypes.Primitives::newDeserializer)
135+
.orNull();
131136
}
132137

133138
private void requireCollectionOfComparableElements(CollectionType actualType, String targetType) {
@@ -310,8 +315,10 @@ public boolean hasDeserializerFor(DeserializationConfig config, Class<?> valueTy
310315
|| ImmutableCollection.class.isAssignableFrom(valueType)
311316
|| ImmutableMap.class.isAssignableFrom(valueType)
312317
|| BiMap.class.isAssignableFrom(valueType)
318+
|| isAssignableFromPrimitive(valueType).isPresent()
313319
;
314320
}
315321
return false;
316322
}
323+
317324
}

guava/src/main/java/com/fasterxml/jackson/datatype/guava/GuavaSerializers.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.fasterxml.jackson.datatype.guava;
22

3+
import com.fasterxml.jackson.databind.type.CollectionLikeType;
4+
import com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes;
35
import java.io.Serializable;
46
import java.util.Set;
57

@@ -48,7 +50,7 @@ public Iterable<?> convert(Object value) {
4850
}
4951

5052
@Override
51-
public ValueSerializer<?> findReferenceSerializer(SerializationConfig config,
53+
public ValueSerializer<?> findReferenceSerializer(SerializationConfig config,
5254
ReferenceType refType, BeanDescription beanDesc, JsonFormat.Value formatOverrides,
5355
TypeSerializer contentTypeSerializer, ValueSerializer<Object> contentValueSerializer)
5456
{
@@ -114,8 +116,21 @@ public ValueSerializer<?> findMapLikeSerializer(SerializationConfig config,
114116
return null;
115117
}
116118

119+
@Override
120+
public ValueSerializer<?> findCollectionLikeSerializer(SerializationConfig config, CollectionLikeType type,
121+
BeanDescription beanDesc, JsonFormat.Value formatOverrides, TypeSerializer elementTypeSerializer,
122+
ValueSerializer<Object> elementValueSerializer)
123+
{
124+
Class<?> raw = type.getRawClass();
125+
Optional<ValueSerializer<?>> primitiveSerializer = PrimitiveTypes.isAssignableFromPrimitive(raw)
126+
.transform((ignore) -> ToStringSerializer.instance);
127+
128+
return primitiveSerializer
129+
.or(() -> super.findCollectionLikeSerializer(config, type, beanDesc, formatOverrides, elementTypeSerializer, elementValueSerializer));
130+
}
131+
117132
private JavaType _findDeclared(JavaType subtype, Class<?> target) {
118-
JavaType decl = subtype.findSuperType(target);
133+
JavaType decl = subtype.findSuperType(target);
119134
if (decl == null) { // should never happen but
120135
throw new IllegalArgumentException("Strange "+target.getName()+" sub-type, "+subtype+", can not find type parameters");
121136
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.fasterxml.jackson.datatype.guava.deser;
2+
3+
import com.fasterxml.jackson.core.JacksonException;
4+
import com.fasterxml.jackson.core.JsonParser;
5+
import com.fasterxml.jackson.core.JsonToken;
6+
import com.fasterxml.jackson.databind.DeserializationContext;
7+
import com.fasterxml.jackson.databind.DeserializationFeature;
8+
import com.fasterxml.jackson.databind.JavaType;
9+
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
10+
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
11+
12+
import java.util.Collection;
13+
import java.util.List;
14+
15+
public abstract class BasePrimitiveCollectionDeserializer<ObjectType, PrimitiveList extends List<ObjectType>, IntermediateCollection extends Collection<ObjectType>>
16+
extends StdDeserializer<PrimitiveList> {
17+
18+
protected BasePrimitiveCollectionDeserializer(Class<? extends PrimitiveList> cls, Class<? super ObjectType> itemType) {
19+
super(cls);
20+
}
21+
22+
protected BasePrimitiveCollectionDeserializer(JavaType type) {
23+
super(type);
24+
}
25+
26+
protected abstract IntermediateCollection createIntermediateCollection();
27+
28+
protected IntermediateCollection createIntermediateCollection(int expectedSize) {
29+
return createIntermediateCollection();
30+
}
31+
32+
protected abstract void add(IntermediateCollection intermediateCollection, JsonParser parser,
33+
DeserializationContext context) throws JacksonException;
34+
35+
protected abstract PrimitiveList finish(IntermediateCollection intermediateCollection);
36+
37+
@Override
38+
public Object deserializeWithType(JsonParser parser, DeserializationContext context,
39+
TypeDeserializer typeDeserializer) throws JacksonException {
40+
return typeDeserializer.deserializeTypedFromArray(parser, context);
41+
}
42+
43+
@SuppressWarnings("unchecked")
44+
@Override
45+
public PrimitiveList deserialize(JsonParser parser, DeserializationContext context)
46+
throws JacksonException {
47+
// Should usually point to START_ARRAY
48+
if (parser.isExpectedStartArrayToken()) {
49+
return _deserializeContents(parser, context);
50+
}
51+
// But may support implicit arrays from single values?
52+
if (context.isEnabled(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) {
53+
return _deserializeFromSingleValue(parser, context);
54+
}
55+
return (PrimitiveList) context.handleUnexpectedToken(getValueType(context), parser);
56+
}
57+
58+
protected PrimitiveList _deserializeContents(JsonParser parser, DeserializationContext context)
59+
throws JacksonException {
60+
IntermediateCollection collection = createIntermediateCollection();
61+
62+
while (parser.nextToken() != JsonToken.END_ARRAY) {
63+
add(collection, parser, context);
64+
}
65+
return finish(collection);
66+
}
67+
68+
protected PrimitiveList _deserializeFromSingleValue(JsonParser parser, DeserializationContext ctxt)
69+
throws JacksonException {
70+
IntermediateCollection intermediateCollection = createIntermediateCollection();
71+
add(intermediateCollection, parser, ctxt);
72+
return finish(intermediateCollection);
73+
}
74+
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.fasterxml.jackson.datatype.guava.deser.primitives;
2+
3+
import com.fasterxml.jackson.core.JacksonException;
4+
import com.fasterxml.jackson.core.JsonParser;
5+
import com.fasterxml.jackson.databind.DeserializationContext;
6+
import com.fasterxml.jackson.datatype.guava.deser.BasePrimitiveCollectionDeserializer;
7+
8+
import java.util.ArrayList;
9+
import java.util.Collection;
10+
import java.util.List;
11+
12+
public abstract class BaseGuavaPrimitivesCollectionDeserializer<ObjectType, PrimitiveList extends List<ObjectType>, IntermediateCollection extends Collection<ObjectType>>
13+
extends BasePrimitiveCollectionDeserializer<ObjectType, PrimitiveList, IntermediateCollection> {
14+
15+
protected BaseGuavaPrimitivesCollectionDeserializer(Class<? extends PrimitiveList> cls, Class<? super ObjectType> itemType) {
16+
super(cls, itemType);
17+
}
18+
19+
@Override
20+
protected IntermediateCollection createIntermediateCollection() {
21+
return (IntermediateCollection) new ArrayList<ObjectType>();
22+
}
23+
24+
@Override
25+
protected void add(IntermediateCollection intermediateCollection, JsonParser parser, DeserializationContext context) throws JacksonException {
26+
intermediateCollection.add(asPrimitive(parser));
27+
}
28+
29+
protected abstract ObjectType asPrimitive(JsonParser parser) throws JacksonException;
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.fasterxml.jackson.datatype.guava.deser.primitives;
2+
3+
import com.fasterxml.jackson.core.JacksonException;
4+
import com.fasterxml.jackson.core.JsonParser;
5+
import com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes;
6+
import com.google.common.primitives.Booleans;
7+
8+
import java.util.Collection;
9+
import java.util.List;
10+
11+
public class BooleansPrimitiveCollectionDeserializer
12+
extends BaseGuavaPrimitivesCollectionDeserializer<Boolean, List<Boolean>, Collection<Boolean>> {
13+
14+
public BooleansPrimitiveCollectionDeserializer() {
15+
super(PrimitiveTypes.BooleansType, Boolean.class);
16+
}
17+
18+
@Override
19+
protected Boolean asPrimitive(JsonParser parser) throws JacksonException {
20+
return parser.getBooleanValue();
21+
}
22+
23+
@Override
24+
protected List<Boolean> finish(Collection<Boolean> booleans) {
25+
return Booleans.asList(Booleans.toArray(booleans));
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.fasterxml.jackson.datatype.guava.deser.primitives;
2+
3+
import com.fasterxml.jackson.core.JacksonException;
4+
import com.fasterxml.jackson.core.JsonParser;
5+
import com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes;
6+
import com.google.common.primitives.Bytes;
7+
8+
import java.util.Collection;
9+
import java.util.List;
10+
11+
public class BytesPrimitiveCollectionDeserializer
12+
extends BaseGuavaPrimitivesCollectionDeserializer<Byte, List<Byte>, Collection<Byte>> {
13+
public BytesPrimitiveCollectionDeserializer() {
14+
super(PrimitiveTypes.BytesType, Byte.class);
15+
}
16+
17+
@Override
18+
protected Byte asPrimitive(JsonParser parser) throws JacksonException {
19+
return parser.getByteValue();
20+
}
21+
22+
@Override
23+
protected List<Byte> finish(Collection<Byte> bytes) {
24+
return Bytes.asList(Bytes.toArray(bytes));
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.fasterxml.jackson.datatype.guava.deser.primitives;
2+
3+
import com.fasterxml.jackson.core.JacksonException;
4+
import com.fasterxml.jackson.core.JsonParser;
5+
import com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes;
6+
import com.google.common.primitives.Chars;
7+
8+
import java.util.Collection;
9+
import java.util.List;
10+
11+
public class CharsPrimitiveCollectionDeserializer
12+
extends BaseGuavaPrimitivesCollectionDeserializer<Character, List<Character>, Collection<Character>> {
13+
public CharsPrimitiveCollectionDeserializer() {
14+
super(PrimitiveTypes.CharsType, Character.class);
15+
}
16+
17+
@Override
18+
protected Character asPrimitive(JsonParser parser) throws JacksonException {
19+
return (char) parser.getValueAsString().toCharArray()[0];
20+
}
21+
22+
@Override
23+
protected List<Character> finish(Collection<Character> characters) {
24+
return Chars.asList(Chars.toArray(characters));
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.fasterxml.jackson.datatype.guava.deser.primitives;
2+
3+
import com.fasterxml.jackson.core.JacksonException;
4+
import com.fasterxml.jackson.core.JsonParser;
5+
import com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes;
6+
import com.google.common.primitives.Doubles;
7+
8+
import java.util.Collection;
9+
import java.util.List;
10+
11+
public class DoublesPrimitiveCollectionDeserializer
12+
extends BaseGuavaPrimitivesCollectionDeserializer<Double, List<Double>, Collection<Double>> {
13+
public DoublesPrimitiveCollectionDeserializer() {
14+
super(PrimitiveTypes.DoublesType, Double.class);
15+
}
16+
17+
@Override
18+
protected Double asPrimitive(JsonParser parser) throws JacksonException {
19+
return parser.getDoubleValue();
20+
}
21+
22+
@Override
23+
protected List<Double> finish(Collection<Double> doubles) {
24+
return Doubles.asList(Doubles.toArray(doubles));
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.fasterxml.jackson.datatype.guava.deser.primitives;
2+
3+
import com.fasterxml.jackson.core.JacksonException;
4+
import com.fasterxml.jackson.core.JsonParser;
5+
import com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes;
6+
import com.google.common.primitives.Floats;
7+
8+
import java.util.Collection;
9+
import java.util.List;
10+
11+
public class FloatsPrimitiveCollectionDeserializer
12+
extends BaseGuavaPrimitivesCollectionDeserializer<Float, List<Float>, Collection<Float>> {
13+
public FloatsPrimitiveCollectionDeserializer() {
14+
super(PrimitiveTypes.FloatsType, Float.class);
15+
}
16+
17+
@Override
18+
protected Float asPrimitive(JsonParser parser) throws JacksonException {
19+
return parser.getFloatValue();
20+
}
21+
22+
@Override
23+
protected List<Float> finish(Collection<Float> floats) {
24+
return Floats.asList(Floats.toArray(floats));
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.fasterxml.jackson.datatype.guava.deser.primitives;
2+
3+
import com.fasterxml.jackson.core.JacksonException;
4+
import com.fasterxml.jackson.core.JsonParser;
5+
import com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes;
6+
import com.google.common.primitives.Ints;
7+
8+
import java.util.Collection;
9+
import java.util.List;
10+
11+
public class IntsPrimitiveCollectionDeserializer
12+
extends BaseGuavaPrimitivesCollectionDeserializer<Integer, List<Integer>, Collection<Integer>> {
13+
public IntsPrimitiveCollectionDeserializer() {
14+
super(PrimitiveTypes.IntsType, Integer.class);
15+
}
16+
17+
@Override
18+
protected Integer asPrimitive(JsonParser parser) throws JacksonException {
19+
return parser.getIntValue();
20+
}
21+
22+
@Override
23+
protected List<Integer> finish(Collection<Integer> integers) {
24+
return Ints.asList(Ints.toArray(integers));
25+
}
26+
}

0 commit comments

Comments
 (0)