From b61a69aa83439846b984945d417c183041f81ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A1szl=C3=B3-R=C3=B3bert=20Albert?= Date: Tue, 23 Mar 2021 02:42:23 +0200 Subject: [PATCH] Add support to serialize and deserialize Guava's Immutable{Double,Int,Long}Array (#86) --- .../datatype/guava/GuavaDeserializers.java | 12 +- .../datatype/guava/GuavaSerializers.java | 5 +- .../BasePrimitiveCollectionDeserializer.java | 32 +++-- .../BaseImmutableArrayDeserializer.java | 23 ++++ .../ImmutableDoubleArrayDeserializer.java | 33 +++++ .../ImmutableIntArrayDeserializer.java | 33 +++++ .../ImmutableLongArrayDeserializer.java | 33 +++++ .../BaseImmutableArraySerializer.java | 24 ++++ .../ImmutableDoubleArraySerializer.java | 20 +++ .../ImmutableIntArraySerializer.java | 20 +++ .../ImmutableLongArraySerializer.java | 20 +++ .../guava/util/ImmutablePrimitiveTypes.java | 115 ++++++++++++++++++ .../datatype/guava/util/PrimitiveTypes.java | 5 +- .../datatype/guava/TestPrimitives.java | 104 ++++++++++++++++ 14 files changed, 458 insertions(+), 21 deletions(-) create mode 100644 guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/BaseImmutableArrayDeserializer.java create mode 100644 guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/ImmutableDoubleArrayDeserializer.java create mode 100644 guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/ImmutableIntArrayDeserializer.java create mode 100644 guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/ImmutableLongArrayDeserializer.java create mode 100644 guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/BaseImmutableArraySerializer.java create mode 100644 guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/ImmutableDoubleArraySerializer.java create mode 100644 guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/ImmutableIntArraySerializer.java create mode 100644 guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/ImmutableLongArraySerializer.java create mode 100644 guava/src/main/java/com/fasterxml/jackson/datatype/guava/util/ImmutablePrimitiveTypes.java diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/GuavaDeserializers.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/GuavaDeserializers.java index d85d399f..bbd56a46 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/GuavaDeserializers.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/GuavaDeserializers.java @@ -1,5 +1,6 @@ package com.fasterxml.jackson.datatype.guava; +import com.fasterxml.jackson.datatype.guava.util.ImmutablePrimitiveTypes; import com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes; import com.google.common.base.Optional; import com.google.common.collect.*; @@ -22,8 +23,6 @@ import java.io.Serializable; -import static com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes.isAssignableFromPrimitive; - /** * Custom deserializers module offers. */ @@ -130,7 +129,7 @@ public ValueDeserializer findCollectionDeserializer(CollectionType type, null, null); } - return isAssignableFromPrimitive(raw) + return PrimitiveTypes.isAssignableFromPrimitive(raw) .transform(PrimitiveTypes.Primitives::newDeserializer) .orNull(); } @@ -298,7 +297,9 @@ public ValueDeserializer findBeanDeserializer(final JavaType type, Deserializ if (type.hasRawClass(HashCode.class)) { return HashCodeDeserializer.std; } - return null; + return ImmutablePrimitiveTypes.isAssignableFromImmutableArray(type.getRawClass()) + .transform(ImmutablePrimitiveTypes.ImmutablePrimitiveArrays::newDeserializer) + .orNull(); } @Override @@ -315,7 +316,8 @@ public boolean hasDeserializerFor(DeserializationConfig config, Class valueTy || ImmutableCollection.class.isAssignableFrom(valueType) || ImmutableMap.class.isAssignableFrom(valueType) || BiMap.class.isAssignableFrom(valueType) - || isAssignableFromPrimitive(valueType).isPresent() + || PrimitiveTypes.isAssignableFromPrimitive(valueType).isPresent() + || ImmutablePrimitiveTypes.isAssignableFromImmutableArray(valueType).isPresent() ; } return false; diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/GuavaSerializers.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/GuavaSerializers.java index 49c1b15e..8cfb81e3 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/GuavaSerializers.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/GuavaSerializers.java @@ -1,6 +1,7 @@ package com.fasterxml.jackson.datatype.guava; import com.fasterxml.jackson.databind.type.CollectionLikeType; +import com.fasterxml.jackson.datatype.guava.util.ImmutablePrimitiveTypes; import com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes; import java.io.Serializable; import java.util.Set; @@ -95,7 +96,9 @@ public ValueSerializer findSerializer(SerializationConfig config, JavaType ty JavaType iterableType = _findDeclared(type, Iterable.class); return new StdDelegatingSerializer(FluentConverter.instance, iterableType, null, null); } - return null; + return ImmutablePrimitiveTypes.isAssignableFromImmutableArray(raw) + .transform(ImmutablePrimitiveTypes.ImmutablePrimitiveArrays::newSerializer) + .orNull(); } @Override diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/BasePrimitiveCollectionDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/BasePrimitiveCollectionDeserializer.java index 343d72a1..2c302c8f 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/BasePrimitiveCollectionDeserializer.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/BasePrimitiveCollectionDeserializer.java @@ -9,10 +9,18 @@ import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; -import java.util.Collection; -import java.util.List; - -public abstract class BasePrimitiveCollectionDeserializer, IntermediateCollection extends Collection> +/** + * Base deserializer of a primitive collection or an immutable primitive array. + * + * @param The base object type. Eg: {@code Long} + * @param The collection type that we deserialize. Eg: type of {@code Longs.asList(..)} or + * {@code ImmutableLongArray} + * @param The intermediate container where we collect the collection elements before returning + * it as the {@code PrimitiveList} type. Eg. in case of collections would be a + * {@code ArrayList} or in case of an immutable array would be + * {@code ImmutableLongArray.Builder} + */ +public abstract class BasePrimitiveCollectionDeserializer extends StdDeserializer { protected BasePrimitiveCollectionDeserializer(Class cls, Class itemType) { @@ -23,16 +31,16 @@ protected BasePrimitiveCollectionDeserializer(JavaType type) { super(type); } - protected abstract IntermediateCollection createIntermediateCollection(); + protected abstract IntermediateContainer createIntermediateCollection(); - protected IntermediateCollection createIntermediateCollection(int expectedSize) { + protected IntermediateContainer createIntermediateCollection(int expectedSize) { return createIntermediateCollection(); } - protected abstract void add(IntermediateCollection intermediateCollection, JsonParser parser, + protected abstract void add(IntermediateContainer intermediateContainer, JsonParser parser, DeserializationContext context) throws JacksonException; - protected abstract PrimitiveList finish(IntermediateCollection intermediateCollection); + protected abstract PrimitiveList finish(IntermediateContainer intermediateContainer); @Override public Object deserializeWithType(JsonParser parser, DeserializationContext context, @@ -57,7 +65,7 @@ public PrimitiveList deserialize(JsonParser parser, DeserializationContext conte protected PrimitiveList _deserializeContents(JsonParser parser, DeserializationContext context) throws JacksonException { - IntermediateCollection collection = createIntermediateCollection(); + IntermediateContainer collection = createIntermediateCollection(); while (parser.nextToken() != JsonToken.END_ARRAY) { add(collection, parser, context); @@ -67,9 +75,9 @@ protected PrimitiveList _deserializeContents(JsonParser parser, DeserializationC protected PrimitiveList _deserializeFromSingleValue(JsonParser parser, DeserializationContext ctxt) throws JacksonException { - IntermediateCollection intermediateCollection = createIntermediateCollection(); - add(intermediateCollection, parser, ctxt); - return finish(intermediateCollection); + IntermediateContainer intermediateContainer = createIntermediateCollection(); + add(intermediateContainer, parser, ctxt); + return finish(intermediateContainer); } } diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/BaseImmutableArrayDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/BaseImmutableArrayDeserializer.java new file mode 100644 index 00000000..059609a2 --- /dev/null +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/BaseImmutableArrayDeserializer.java @@ -0,0 +1,23 @@ +package com.fasterxml.jackson.datatype.guava.deser.primitives; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.datatype.guava.deser.BasePrimitiveCollectionDeserializer; + +public abstract class BaseImmutableArrayDeserializer + extends BasePrimitiveCollectionDeserializer { + + protected BaseImmutableArrayDeserializer(Class cls, Class itemType) { + super(cls, itemType); + } + + @Override + protected final void add(IntermediateArrayBuilder intermediateBuilder, JsonParser parser, DeserializationContext context) throws JacksonException { + collect(intermediateBuilder, asPrimitive(parser)); + } + + protected abstract void collect(IntermediateArrayBuilder intermediateBuilder, ObjectType value); + + protected abstract ObjectType asPrimitive(JsonParser parser) throws JacksonException; +} diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/ImmutableDoubleArrayDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/ImmutableDoubleArrayDeserializer.java new file mode 100644 index 00000000..dc3f56ea --- /dev/null +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/ImmutableDoubleArrayDeserializer.java @@ -0,0 +1,33 @@ +package com.fasterxml.jackson.datatype.guava.deser.primitives; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.datatype.guava.util.ImmutablePrimitiveTypes; +import com.google.common.primitives.ImmutableDoubleArray; + +public class ImmutableDoubleArrayDeserializer + extends BaseImmutableArrayDeserializer { + public ImmutableDoubleArrayDeserializer() { + super(ImmutablePrimitiveTypes.ImmutableDoubleArrayType, Double.class); + } + + @Override + protected ImmutableDoubleArray.Builder createIntermediateCollection() { + return ImmutableDoubleArray.builder(); + } + + @Override + protected void collect(ImmutableDoubleArray.Builder intermediateBuilder, Double value) { + intermediateBuilder.add(value); + } + + @Override + protected ImmutableDoubleArray finish(ImmutableDoubleArray.Builder builder) { + return builder.build(); + } + + @Override + protected Double asPrimitive(JsonParser parser) throws JacksonException { + return parser.getDoubleValue(); + } +} \ No newline at end of file diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/ImmutableIntArrayDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/ImmutableIntArrayDeserializer.java new file mode 100644 index 00000000..fb276658 --- /dev/null +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/ImmutableIntArrayDeserializer.java @@ -0,0 +1,33 @@ +package com.fasterxml.jackson.datatype.guava.deser.primitives; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.datatype.guava.util.ImmutablePrimitiveTypes; +import com.google.common.primitives.ImmutableIntArray; + +public class ImmutableIntArrayDeserializer + extends BaseImmutableArrayDeserializer { + public ImmutableIntArrayDeserializer() { + super(ImmutablePrimitiveTypes.ImmutableIntArrayType, Integer.class); + } + + @Override + protected ImmutableIntArray.Builder createIntermediateCollection() { + return ImmutableIntArray.builder(); + } + + @Override + protected void collect(ImmutableIntArray.Builder intermediateBuilder, Integer value) { + intermediateBuilder.add(value); + } + + @Override + protected ImmutableIntArray finish(ImmutableIntArray.Builder builder) { + return builder.build(); + } + + @Override + protected Integer asPrimitive(JsonParser parser) throws JacksonException { + return parser.getIntValue(); + } +} \ No newline at end of file diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/ImmutableLongArrayDeserializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/ImmutableLongArrayDeserializer.java new file mode 100644 index 00000000..b963f79c --- /dev/null +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/deser/primitives/ImmutableLongArrayDeserializer.java @@ -0,0 +1,33 @@ +package com.fasterxml.jackson.datatype.guava.deser.primitives; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.datatype.guava.util.ImmutablePrimitiveTypes; +import com.google.common.primitives.ImmutableLongArray; + +public class ImmutableLongArrayDeserializer + extends BaseImmutableArrayDeserializer { + public ImmutableLongArrayDeserializer() { + super(ImmutablePrimitiveTypes.ImmutableLongArrayType, Long.class); + } + + @Override + protected ImmutableLongArray.Builder createIntermediateCollection() { + return ImmutableLongArray.builder(); + } + + @Override + protected void collect(ImmutableLongArray.Builder intermediateBuilder, Long value) { + intermediateBuilder.add(value); + } + + @Override + protected ImmutableLongArray finish(ImmutableLongArray.Builder builder) { + return builder.build(); + } + + @Override + protected Long asPrimitive(JsonParser parser) throws JacksonException { + return parser.getLongValue(); + } +} \ No newline at end of file diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/BaseImmutableArraySerializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/BaseImmutableArraySerializer.java new file mode 100644 index 00000000..366eda67 --- /dev/null +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/BaseImmutableArraySerializer.java @@ -0,0 +1,24 @@ +package com.fasterxml.jackson.datatype.guava.ser.primitives; + +import com.fasterxml.jackson.core.JacksonException; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import com.fasterxml.jackson.datatype.guava.util.ImmutablePrimitiveTypes; + +public abstract class BaseImmutableArraySerializer extends StdSerializer { + protected BaseImmutableArraySerializer(ImmutablePrimitiveTypes.ImmutablePrimitiveArrays immutableArrayType) { + super(immutableArrayType.type()); + } + + @Override + public final void serialize(ImmutableArray immutableArray, JsonGenerator gen, SerializerProvider provider) throws JacksonException { + if (immutableArray == null) { + provider.defaultSerializeNullValue(gen); + } else { + writeArray(immutableArray, gen); + } + } + + protected abstract void writeArray(ImmutableArray immutableArray, JsonGenerator gen); +} diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/ImmutableDoubleArraySerializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/ImmutableDoubleArraySerializer.java new file mode 100644 index 00000000..6529f965 --- /dev/null +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/ImmutableDoubleArraySerializer.java @@ -0,0 +1,20 @@ +package com.fasterxml.jackson.datatype.guava.ser.primitives; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.datatype.guava.util.ImmutablePrimitiveTypes; +import com.google.common.primitives.ImmutableDoubleArray; + +public class ImmutableDoubleArraySerializer extends BaseImmutableArraySerializer { + + public ImmutableDoubleArraySerializer() { + super(ImmutablePrimitiveTypes.ImmutablePrimitiveArrays.DOUBLE); + } + + @Override + protected void writeArray(ImmutableDoubleArray immutableArray, JsonGenerator gen) { + if (!immutableArray.isEmpty()) { + gen.writeArray(immutableArray.toArray(), 0, immutableArray.length()); + } + } + +} diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/ImmutableIntArraySerializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/ImmutableIntArraySerializer.java new file mode 100644 index 00000000..c344eb76 --- /dev/null +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/ImmutableIntArraySerializer.java @@ -0,0 +1,20 @@ +package com.fasterxml.jackson.datatype.guava.ser.primitives; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.datatype.guava.util.ImmutablePrimitiveTypes; +import com.google.common.primitives.ImmutableIntArray; + +public class ImmutableIntArraySerializer extends BaseImmutableArraySerializer { + + public ImmutableIntArraySerializer() { + super(ImmutablePrimitiveTypes.ImmutablePrimitiveArrays.INT); + } + + @Override + protected void writeArray(ImmutableIntArray immutableArray, JsonGenerator gen) { + if (!immutableArray.isEmpty()) { + gen.writeArray(immutableArray.toArray(), 0, immutableArray.length()); + } + } + +} diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/ImmutableLongArraySerializer.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/ImmutableLongArraySerializer.java new file mode 100644 index 00000000..c73fd8b5 --- /dev/null +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/ser/primitives/ImmutableLongArraySerializer.java @@ -0,0 +1,20 @@ +package com.fasterxml.jackson.datatype.guava.ser.primitives; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.datatype.guava.util.ImmutablePrimitiveTypes; +import com.google.common.primitives.ImmutableLongArray; + +public class ImmutableLongArraySerializer extends BaseImmutableArraySerializer { + + public ImmutableLongArraySerializer() { + super(ImmutablePrimitiveTypes.ImmutablePrimitiveArrays.LONG); + } + + @Override + protected void writeArray(ImmutableLongArray immutableArray, JsonGenerator gen) { + if (!immutableArray.isEmpty()) { + gen.writeArray(immutableArray.toArray(), 0, immutableArray.length()); + } + } + +} diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/util/ImmutablePrimitiveTypes.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/util/ImmutablePrimitiveTypes.java new file mode 100644 index 00000000..640a5365 --- /dev/null +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/util/ImmutablePrimitiveTypes.java @@ -0,0 +1,115 @@ +package com.fasterxml.jackson.datatype.guava.util; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.datatype.guava.deser.primitives.BaseImmutableArrayDeserializer; +import com.fasterxml.jackson.datatype.guava.deser.primitives.ImmutableDoubleArrayDeserializer; +import com.fasterxml.jackson.datatype.guava.deser.primitives.ImmutableIntArrayDeserializer; +import com.fasterxml.jackson.datatype.guava.deser.primitives.ImmutableLongArrayDeserializer; +import com.fasterxml.jackson.datatype.guava.ser.primitives.BaseImmutableArraySerializer; +import com.fasterxml.jackson.datatype.guava.ser.primitives.ImmutableDoubleArraySerializer; +import com.fasterxml.jackson.datatype.guava.ser.primitives.ImmutableIntArraySerializer; +import com.fasterxml.jackson.datatype.guava.ser.primitives.ImmutableLongArraySerializer; +import com.google.common.base.Optional; +import com.google.common.primitives.ImmutableDoubleArray; +import com.google.common.primitives.ImmutableIntArray; +import com.google.common.primitives.ImmutableLongArray; + +import java.io.Serializable; +import java.util.function.Supplier; + +import static com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes.typeRefOf; + +/** + * Utility class to cover all {@code Immutable[Primitive]Array} primitive types + * + * @author robert@albertlr.ro + */ +public class ImmutablePrimitiveTypes { + /** + * An enum with all the primitives + */ + public enum ImmutablePrimitiveArrays { + INT(ImmutableIntArrayType, int.class, Integer.class, + ImmutableIntArraySerializer::new, + ImmutableIntArrayDeserializer::new + ), + DOUBLE(ImmutableDoubleArrayType, double.class, Double.class, + ImmutableDoubleArraySerializer::new, + ImmutableDoubleArrayDeserializer::new + ), + LONG(ImmutableLongArrayType, long.class, Long.class, + ImmutableLongArraySerializer::new, + ImmutableLongArrayDeserializer::new + ); + + private final Class type; + private final Class primitiveType; + private final Class objectType; + private final Supplier serializerFactory; + private final Supplier deserializerFactory; + + private ImmutablePrimitiveArrays(Class type, Class primitiveType, Class objectType, + Supplier serializerFactory, + Supplier deserializerFactory) { + this.type = type; + this.primitiveType = primitiveType; + this.objectType = objectType; + this.deserializerFactory = deserializerFactory; + this.serializerFactory = serializerFactory; + } + + public Class type() { + return type; + } + + public Class primitiveType() { + return primitiveType; + } + + public Class objectType() { + return (Class) objectType; + } + + public BaseImmutableArraySerializer newSerializer() { + return serializerFactory.get(); + } + + public StdDeserializer newDeserializer() { + return deserializerFactory.get(); + } + + } + + public static Optional isAssignableFromImmutableArray(Class immutableArrayType) { + for (ImmutablePrimitiveArrays primitive : ImmutablePrimitiveArrays.values()) { + if (primitive.type().isAssignableFrom(immutableArrayType)) { + return Optional.of(primitive); + } + } + return Optional.absent(); + } + + + /** + * Type of array returned by {@link ImmutableIntArray} + */ + public static final Class ImmutableIntArrayType = ImmutableIntArray.class; + /** + * Type of array returned by {@link ImmutableLongArray} + */ + public static final Class ImmutableLongArrayType = ImmutableLongArray.class; + /** + * Type of array returned by {@link ImmutableDoubleArray} + */ + public static final Class ImmutableDoubleArrayType = ImmutableDoubleArray.class; + + public static final TypeReference ImmutableIntArrayReference = typeRefOf(ImmutableIntArrayType); + public static final TypeReference ImmutableLongArrayReference = typeRefOf(ImmutableLongArrayType); + public static final TypeReference ImmutableDoubleArrayReference = typeRefOf(ImmutableDoubleArrayType); + + public static final String ImmutableIntArrayName = ImmutableIntArrayType.getName(); + public static final String ImmutableLongArrayName = ImmutableLongArrayType.getName(); + public static final String ImmutableDoubleArrayName = ImmutableDoubleArrayType.getName(); + +} diff --git a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/util/PrimitiveTypes.java b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/util/PrimitiveTypes.java index f9a01cdd..a7aa7b1f 100644 --- a/guava/src/main/java/com/fasterxml/jackson/datatype/guava/util/PrimitiveTypes.java +++ b/guava/src/main/java/com/fasterxml/jackson/datatype/guava/util/PrimitiveTypes.java @@ -131,12 +131,11 @@ public static Optional isAssignableFromPrimitive(Clas public static final String LongsTypeName = LongsType.getName(); public static final String ShortsTypeName = ShortsType.getName(); - - private static TypeReference typeRefOf(Type type) { + static TypeReference typeRefOf(Type type) { return new PrimitiveTypeReference<>(type); } - private static class PrimitiveTypeReference extends TypeReference { + static class PrimitiveTypeReference extends TypeReference { private final Type primitiveType; private PrimitiveTypeReference(Type primitiveType) { diff --git a/guava/src/test/java/com/fasterxml/jackson/datatype/guava/TestPrimitives.java b/guava/src/test/java/com/fasterxml/jackson/datatype/guava/TestPrimitives.java index 450deb98..0406013c 100644 --- a/guava/src/test/java/com/fasterxml/jackson/datatype/guava/TestPrimitives.java +++ b/guava/src/test/java/com/fasterxml/jackson/datatype/guava/TestPrimitives.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator; +import com.fasterxml.jackson.datatype.guava.util.ImmutablePrimitiveTypes; import com.fasterxml.jackson.datatype.guava.util.PrimitiveTypes; import com.google.common.primitives.Booleans; import com.google.common.primitives.Bytes; @@ -83,6 +84,33 @@ public void testWithoutSerializers() throws Exception { assertEquals("[1,2,3]", MAPPER.writeValueAsString(Shorts.asList((short) 1, (short) 2, (short) 3))); } + /** + * {@link ImmutableIntArray}, {@link ImmutableLongArray} and {@link ImmutableDoubleArray} cannot be serialized by + * default. + */ + public void testImmutableArraysWithoutSerializers() { + ObjectMapper mapper = new ObjectMapper(); + ImmutableIntArray intArray = ImmutableIntArray.of(1, 2, 3); + assertEquals("[1, 2, 3]", intArray.toString()); + assertEquals("{\"empty\":false}", mapper.writeValueAsString(intArray)); + ImmutableLongArray longArray = ImmutableLongArray.of(1, 2, 3); + assertEquals("[1, 2, 3]", longArray.toString()); + assertEquals("{\"empty\":false}", mapper.writeValueAsString(longArray)); + ImmutableDoubleArray doubleArray = ImmutableDoubleArray.of(1.5, 2.5, 3.5); + assertEquals("[1.5, 2.5, 3.5]", doubleArray.toString()); + assertEquals("{\"empty\":false}", mapper.writeValueAsString(doubleArray)); + } + + /** + * {@link ImmutableIntArray}, {@link ImmutableLongArray} and {@link ImmutableDoubleArray} cannot be serialized by + * default, however having {@link GuavaModule} registered, it will successfully serialize them as plain arrays. + */ + public void testImmutableArraysWithSerializers() { + assertEquals("[1,2,3]", MAPPER.writeValueAsString(ImmutableIntArray.of(1, 2, 3))); + assertEquals("[1,2,3]", MAPPER.writeValueAsString(ImmutableLongArray.of(1, 2, 3))); + assertEquals("[1.5,2.5,3.5]", MAPPER.writeValueAsString(ImmutableDoubleArray.of(1.5, 2.5, 3.5))); + } + /** * Deserialization will fail, however. */ @@ -111,6 +139,34 @@ public void testWithoutDeserializers() throws Exception { } + /** + * Deserialization will fail. + */ + public void testImmutableArraysWithoutDeserializers() throws Exception { + ObjectMapper mapper = new ObjectMapper(); + try { + mapper.readValue("[1,2,3]", ImmutablePrimitiveTypes.ImmutableIntArrayType); + fail("Expected failure for missing deserializer"); + } catch (JacksonException e) { + verifyException(e, ImmutablePrimitiveTypes.ImmutableIntArrayName); + } + + try { + mapper.readValue("[1,2,3]", ImmutablePrimitiveTypes.ImmutableLongArrayType); + fail("Expected failure for missing deserializer"); + } catch (JacksonException e) { + verifyException(e, ImmutablePrimitiveTypes.ImmutableLongArrayName); + } + + try { + mapper.readValue("[1.5,2.5,3.5]", ImmutablePrimitiveTypes.ImmutableDoubleArrayType); + fail("Expected failure for missing deserializer"); + } catch (JacksonException e) { + verifyException(e, ImmutablePrimitiveTypes.ImmutableDoubleArrayName); + } + + } + /********************************************************************** * Basic tests for actual registered module /***********************************************************************/ @@ -200,6 +256,22 @@ public void testDoublesFromSingle() throws Exception { assertTrue(list.getClass().getName().equals(PrimitiveTypes.DoublesTypeName)); } + public void testImmutableDoubleArray() throws Exception { + ImmutableDoubleArray list = MAPPER.readValue("[1.5,2.5,3.5]", ImmutablePrimitiveTypes.ImmutableDoubleArrayReference); + assertEquals(3, list.length()); + assertEquals(Double.valueOf(1.5), list.get(0)); + assertEquals(Double.valueOf(2.5), list.get(1)); + assertEquals(Double.valueOf(3.5), list.get(2)); + assertTrue(list.getClass().getName().equals(ImmutablePrimitiveTypes.ImmutableDoubleArrayName)); + } + + public void testImmutableDoubleArrayFromSingle() throws Exception { + ImmutableDoubleArray array = SINGLE_MAPPER.readValue("1", ImmutablePrimitiveTypes.ImmutableDoubleArrayType); + assertEquals(1, array.length()); + assertEquals(Double.valueOf(1d), array.get(0)); + assertTrue(array.getClass().getName().equals(ImmutablePrimitiveTypes.ImmutableDoubleArrayName)); + } + public void testInts() throws Exception { List list = MAPPER.readValue("[1,2,3]", PrimitiveTypes.IntsTypeReference); assertEquals(3, list.size()); @@ -216,6 +288,22 @@ public void testIntsFromSingle() throws Exception { assertTrue(list.getClass().getName().equals(PrimitiveTypes.IntsTypeName)); } + public void testImmutableIntArray() throws Exception { + ImmutableIntArray array = MAPPER.readValue("[1,2,3]", ImmutablePrimitiveTypes.ImmutableIntArrayReference); + assertEquals(3, array.length()); + assertEquals(1, array.get(0)); + assertEquals(2, array.get(1)); + assertEquals(3, array.get(2)); + assertTrue(array.getClass().getName().equals(ImmutablePrimitiveTypes.ImmutableIntArrayName)); + } + + public void testImmutableIntArrayFromSingle() throws Exception { + ImmutableIntArray array = SINGLE_MAPPER.readValue("1", ImmutablePrimitiveTypes.ImmutableIntArrayReference); + assertEquals(1, array.length()); + assertEquals(1, array.get(0)); + assertTrue(array.getClass().getName().equals(ImmutablePrimitiveTypes.ImmutableIntArrayName)); + } + public void testLongs() throws Exception { List list = MAPPER.readValue("[1,2,3]", PrimitiveTypes.LongsTypeReference); assertEquals(3, list.size()); @@ -232,6 +320,22 @@ public void testLongsFromSingle() throws Exception { assertTrue(list.getClass().getName().equals(PrimitiveTypes.LongsTypeName)); } + public void testImmutableLongArray() throws Exception { + ImmutableLongArray array = MAPPER.readValue("[1,2,3]", ImmutablePrimitiveTypes.ImmutableLongArrayReference); + assertEquals(3, array.length()); + assertEquals(1L, array.get(0)); + assertEquals(2L, array.get(1)); + assertEquals(3L, array.get(2)); + assertTrue(array.getClass().getName().equals(ImmutablePrimitiveTypes.ImmutableLongArrayName)); + } + + public void testImmutableLongArrayFromSingle() throws Exception { + ImmutableLongArray array = SINGLE_MAPPER.readValue("1", ImmutablePrimitiveTypes.ImmutableLongArrayReference); + assertEquals(1, array.length()); + assertEquals(1L, array.get(0)); + assertTrue(array.getClass().getName().equals(ImmutablePrimitiveTypes.ImmutableLongArrayName)); + } + public void testShorts() throws Exception { List list = MAPPER.readValue("[1,2,3]", PrimitiveTypes.ShortsTypeReference); assertEquals(3, list.size());