UnrolledBeanSerializer.java
package tools.jackson.databind.ser;
import java.util.Set;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.*;
import tools.jackson.databind.annotation.JacksonStdImpl;
import tools.jackson.databind.ser.bean.BeanAsArraySerializer;
import tools.jackson.databind.ser.bean.BeanSerializerBase;
import tools.jackson.databind.ser.bean.UnwrappingBeanSerializer;
import tools.jackson.databind.ser.impl.ObjectIdWriter;
import tools.jackson.databind.util.NameTransformer;
/**
* @since 3.0
*/
@JacksonStdImpl
public class UnrolledBeanSerializer
extends BeanSerializerBase
{
/* 28-Oct-2017, tatu: Exact choice for max number of properties to unroll
* is difficult to pin down, but probably has to be at least 4, and
* at most 8. Partly this is due to "blocks of 4" that default bean
* serializer now uses, and partly guessing how aggressively JVM might
* inline larger methods (more unroll, bigger method).
*/
private static final int MAX_PROPS = 6;
protected final int _propCount;
// // // We store separate references in form more easily accessed
// // // from switch statement
protected BeanPropertyWriter _prop1;
protected BeanPropertyWriter _prop2;
protected BeanPropertyWriter _prop3;
protected BeanPropertyWriter _prop4;
protected BeanPropertyWriter _prop5;
protected BeanPropertyWriter _prop6;
/*
/**********************************************************************
/* Life-cycle: constructors
/**********************************************************************
*/
/**
* @param builder Builder object that contains collected information
* that may be needed for serializer
* @param properties Property writers used for actual serialization
*/
public UnrolledBeanSerializer(JavaType type, BeanSerializerBuilder builder,
BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties)
{
super(type, builder, properties, filteredProperties);
_propCount = _props.length;
_calcUnrolled();
}
protected UnrolledBeanSerializer(UnrolledBeanSerializer src,
Set<String> toIgnore, Set<String> toInclude) {
super(src, toIgnore, toInclude);
_propCount = _props.length;
_calcUnrolled();
}
protected UnrolledBeanSerializer(UnrolledBeanSerializer src,
BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties) {
super(src, properties, filteredProperties);
_propCount = _props.length;
_calcUnrolled();
}
private void _calcUnrolled() {
BeanPropertyWriter[] oProps = new BeanPropertyWriter[6];
int offset = 6 - _propCount;
System.arraycopy(_props, 0, oProps, offset, _propCount);
_prop1 = oProps[0];
_prop2 = oProps[1];
_prop3 = oProps[2];
_prop4 = oProps[3];
_prop5 = oProps[4];
_prop6 = oProps[5];
}
/**
* Factory method that will construct optimized instance if all the constraints
* are obeyed; or, if not, return `null` to indicate that instance cannot be
* created.
*/
public static UnrolledBeanSerializer tryConstruct(JavaType type, BeanSerializerBuilder builder,
BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties)
{
if ((properties.length > MAX_PROPS)
|| (builder.getFilterId() != null)) {
return null;
}
return new UnrolledBeanSerializer(type, builder, properties, filteredProperties);
}
/*
/**********************************************************************
/* Life-cycle: factory methods, fluent factories
/**********************************************************************
*/
@Override
public ValueSerializer<Object> unwrappingSerializer(NameTransformer unwrapper) {
return new UnwrappingBeanSerializer(this, unwrapper);
}
@Override
public BeanSerializerBase withObjectIdWriter(ObjectIdWriter objectIdWriter) {
// Revert to Vanilla variant, if so:
return new BeanSerializer(this, objectIdWriter, _propertyFilterId);
}
@Override
public BeanSerializerBase withFilterId(Object filterId) {
// Revert to Vanilla variant, if so:
return new BeanSerializer(this, _objectIdWriter, filterId);
}
@Override
public ValueSerializer<?> withIgnoredProperties(Set<String> toIgnore) {
// Revert to Vanilla variant here as well
return new BeanSerializer(this, toIgnore, null);
}
@Override
protected BeanSerializerBase withByNameInclusion(Set<String> toIgnore, Set<String> toInclude) {
return new UnrolledBeanSerializer(this, toIgnore, toInclude);
}
@Override
protected BeanSerializerBase withProperties(BeanPropertyWriter[] properties,
BeanPropertyWriter[] filteredProperties) {
return new UnrolledBeanSerializer(this, properties, filteredProperties);
}
@Override
protected BeanSerializerBase asArraySerializer()
{
if (canCreateArraySerializer()) {
return BeanAsArraySerializer.construct(this);
}
// Can't... so use this one
return this;
}
@Override
public void resolve(SerializationContext provider)
{
super.resolve(provider);
_calcUnrolled();
}
/*
/**********************************************************************
/* ValueSerializer implementation that differs between impls
/**********************************************************************
*/
@Override
public void serialize(Object bean, JsonGenerator gen, SerializationContext provider)
throws JacksonException
{
// NOTE! We have ensured that "JSON Filter" and "Object Id" cases
// always use "vanilla" BeanSerializer, so no need to check here
BeanPropertyWriter[] fProps = _filteredProps;
if ((fProps != null) && (provider.getActiveView() != null)) {
gen.writeStartObject(bean);
_serializePropertiesMaybeView(bean, gen, provider, fProps);
gen.writeEndObject();
return;
}
serializeNonFiltered(bean, gen, provider);
}
protected void serializeNonFiltered(Object bean, JsonGenerator gen, SerializationContext provider)
throws JacksonException
{
gen.writeStartObject(bean);
BeanPropertyWriter prop = null;
try {
switch (_propCount) {
default:
//case 6:
prop = _prop1;
prop.serializeAsProperty(bean, gen, provider);
// fall through
case 5:
prop = _prop2;
prop.serializeAsProperty(bean, gen, provider);
case 4:
prop = _prop3;
prop.serializeAsProperty(bean, gen, provider);
case 3:
prop = _prop4;
prop.serializeAsProperty(bean, gen, provider);
case 2:
prop = _prop5;
prop.serializeAsProperty(bean, gen, provider);
case 1:
prop = _prop6;
prop.serializeAsProperty(bean, gen, provider);
case 0:
}
prop = null;
} catch (Exception e) {
String name = (prop == null) ? "[anySetter]" : prop.getName();
wrapAndThrow(provider, e, bean, name);
} catch (StackOverflowError e) {
final String name = (prop == null) ? "[anySetter]" : prop.getName();
throw DatabindException.from(gen, "Infinite recursion (StackOverflowError)", e)
.prependPath(bean, name);
}
gen.writeEndObject();
}
}