Include Jackson JSON serializers for BigDecimals and BigIntegers as well as generating typeless Collection JSON.
Resolves gh-67.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.jackson.databind.serializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
||||
import com.fasterxml.jackson.databind.ser.std.NumberSerializers;
|
||||
|
||||
/**
|
||||
* The {@link BigDecimalSerializer} class is a {@link NumberSerializers.Base} serializer
|
||||
* for serializing {@link BigDecimal} values.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.math.BigDecimal
|
||||
* @see com.fasterxml.jackson.databind.ser.std.NumberSerializers
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class BigDecimalSerializer extends NumberSerializers.Base<BigDecimal> {
|
||||
|
||||
public static final BigDecimalSerializer INSTANCE = new BigDecimalSerializer();
|
||||
|
||||
public BigDecimalSerializer() {
|
||||
super(BigDecimal.class, JsonParser.NumberType.BIG_DECIMAL, "bigdecimal");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(BigDecimal value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
|
||||
throws IOException {
|
||||
|
||||
jsonGenerator.writeNumber(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWithType(BigDecimal value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider,
|
||||
TypeSerializer typeSerializer) throws IOException {
|
||||
|
||||
serialize(value, jsonGenerator, serializerProvider);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.jackson.databind.serializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
||||
import com.fasterxml.jackson.databind.ser.std.NumberSerializers;
|
||||
|
||||
/**
|
||||
* The {@link BigIntegerSerializer} class is a {@link NumberSerializers.Base} serializer
|
||||
* for serializing {@link BigInteger} values.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.math.BigInteger
|
||||
* @see com.fasterxml.jackson.databind.ser.std.NumberSerializers
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class BigIntegerSerializer extends NumberSerializers.Base<BigInteger> {
|
||||
|
||||
public static final BigIntegerSerializer INSTANCE = new BigIntegerSerializer();
|
||||
|
||||
public BigIntegerSerializer() {
|
||||
super(BigInteger.class, JsonParser.NumberType.BIG_INTEGER, "biginteger");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(BigInteger value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
|
||||
throws IOException {
|
||||
|
||||
jsonGenerator.writeNumber(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWithType(BigInteger value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider,
|
||||
TypeSerializer typeSerializer) throws IOException {
|
||||
|
||||
serialize(value, jsonGenerator, serializerProvider);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing
|
||||
* permissions and limitations under the License.
|
||||
*/
|
||||
package org.springframework.geode.jackson.databind.serializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.databind.BeanProperty;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
|
||||
import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
|
||||
import com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase;
|
||||
import com.fasterxml.jackson.databind.ser.std.CollectionSerializer;
|
||||
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* The {@link TypelessCollectionSerializer} class is a custom, typeless {@link CollectionSerializer} implementation.
|
||||
*
|
||||
* This {@link AsArraySerializerBase} implementation is a lot like {@link CollectionSerializer}, however it excludes
|
||||
* unnecessary type metadata in the context of GemFire/Geode.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see java.util.Collection
|
||||
* @see com.fasterxml.jackson.core.JsonGenerator
|
||||
* @see com.fasterxml.jackson.databind.JsonSerializer
|
||||
* @see com.fasterxml.jackson.databind.ObjectMapper
|
||||
* @see com.fasterxml.jackson.databind.SerializerProvider
|
||||
* @see com.fasterxml.jackson.databind.ser.std.AsArraySerializerBase
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class TypelessCollectionSerializer extends AsArraySerializerBase<Collection<?>> {
|
||||
|
||||
protected static final boolean DEFAULT_UNWRAP_SINGLE = false;
|
||||
protected static final boolean DEFAULT_STATIC_TYPING = false;
|
||||
|
||||
public TypelessCollectionSerializer(ObjectMapper mapper) {
|
||||
super(Collection.class, mapper.getTypeFactory().constructType(Object.class), DEFAULT_STATIC_TYPING,
|
||||
null, null);
|
||||
}
|
||||
|
||||
public TypelessCollectionSerializer(TypelessCollectionSerializer serializer, BeanProperty property,
|
||||
TypeSerializer typeSerializer, JsonSerializer<?> elementSerializer) {
|
||||
|
||||
super(serializer, property, typeSerializer, elementSerializer, DEFAULT_UNWRAP_SINGLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serializeWithType(Collection<?> value, JsonGenerator jsonGenerator,
|
||||
SerializerProvider serializerProvider, TypeSerializer typeSerializer) throws IOException {
|
||||
|
||||
serialize(value, jsonGenerator, serializerProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSingleElement(Collection<?> value) {
|
||||
return value != null && value.size() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void serializeContents(Collection<?> value, JsonGenerator jsonGenerator,
|
||||
SerializerProvider serializerProvider) throws IOException {
|
||||
|
||||
jsonGenerator.setCurrentValue(value);
|
||||
|
||||
PropertySerializerMap serializers = this._dynamicSerializers;
|
||||
TypeSerializer typeSerializer = this._valueTypeSerializer;
|
||||
|
||||
int index = -1;
|
||||
|
||||
try {
|
||||
for (Object element : CollectionUtils.nullSafeCollection(value)) {
|
||||
|
||||
index++;
|
||||
|
||||
if (Objects.isNull(element)) {
|
||||
serializerProvider.defaultSerializeNull(jsonGenerator);
|
||||
}
|
||||
else {
|
||||
|
||||
Class<?> elementType = element.getClass();
|
||||
|
||||
JsonSerializer<Object> serializer = resolveSerializer(serializerProvider, elementType);
|
||||
|
||||
if (typeSerializer != null) {
|
||||
serializer.serializeWithType(element, jsonGenerator, serializerProvider, typeSerializer);
|
||||
}
|
||||
else {
|
||||
serializer.serialize(element, jsonGenerator, serializerProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception cause) {
|
||||
wrapAndThrow(serializerProvider, cause, value, index);
|
||||
}
|
||||
}
|
||||
|
||||
private JavaType constructSpecializedType(SerializerProvider serializerProvider, JavaType baseType, Class<?> subclass) {
|
||||
return serializerProvider.constructSpecializedType(baseType, subclass);
|
||||
}
|
||||
|
||||
private JsonSerializer<Object> resolveSerializer(SerializerProvider serializerProvider, Class<?> type)
|
||||
throws JsonMappingException {
|
||||
|
||||
JsonSerializer<Object> resolvedSerializer = this._elementSerializer;
|
||||
|
||||
if (Objects.isNull(resolvedSerializer)) {
|
||||
|
||||
PropertySerializerMap dynamicSerializers = this._dynamicSerializers;
|
||||
|
||||
resolvedSerializer = dynamicSerializers.serializerFor(type);
|
||||
|
||||
if (Objects.isNull(resolvedSerializer)) {
|
||||
resolvedSerializer = Objects.nonNull(this._elementType) && this._elementType.hasGenericTypes()
|
||||
? this._findAndAddDynamic(dynamicSerializers,
|
||||
constructSpecializedType(serializerProvider, this._elementType, type), serializerProvider)
|
||||
: this._findAndAddDynamic(dynamicSerializers, type, serializerProvider);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return resolvedSerializer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypelessCollectionSerializer withResolved(BeanProperty property, TypeSerializer typeSerializer,
|
||||
JsonSerializer<?> elementSerializer, Boolean unwrapSingle) {
|
||||
|
||||
return new TypelessCollectionSerializer(this, property, typeSerializer, elementSerializer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypelessCollectionSerializer _withValueTypeSerializer(TypeSerializer typeSerializer) {
|
||||
return new TypelessCollectionSerializer(this, this._property, typeSerializer, this._elementSerializer);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user