-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
UnrolledBeanSerializer.java
209 lines (185 loc) · 7.18 KB
/
UnrolledBeanSerializer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
package com.fasterxml.jackson.databind.ser;
import java.io.IOException;
import java.util.Set;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
import com.fasterxml.jackson.databind.ser.impl.BeanAsArraySerializer;
import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter;
import com.fasterxml.jackson.databind.ser.impl.UnwrappingBeanSerializer;
import com.fasterxml.jackson.databind.ser.std.BeanSerializerBase;
import com.fasterxml.jackson.databind.util.NameTransformer;
/**
* @since 3.0
*/
@JacksonStdImpl
public class UnrolledBeanSerializer
extends BeanSerializerBase
{
private static final long serialVersionUID = 30; // as per jackson 3.0
/* 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) {
super(src, toIgnore);
_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 can not 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 JsonSerializer<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
protected BeanSerializerBase withIgnorals(Set<String> toIgnore) {
return new UnrolledBeanSerializer(this, toIgnore);
}
@Override
protected BeanSerializerBase asArraySerializer()
{
if (canCreateArraySerializer()) {
return BeanAsArraySerializer.construct(this);
}
// Can't... so use this one
return this;
}
@Override
public void resolve(SerializerProvider provider) throws JsonMappingException
{
super.resolve(provider);
_calcUnrolled();
}
/*
/**********************************************************
/* JsonSerializer implementation that differs between impls
/**********************************************************
*/
@Override
public void serialize(Object bean, JsonGenerator gen, SerializerProvider provider)
throws IOException
{
// 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);
_serializeFieldsWithView(bean, gen, provider, fProps);
gen.writeEndObject();
return;
}
serializeNonFiltered(bean, gen, provider);
}
protected void serializeNonFiltered(Object bean, JsonGenerator gen, SerializerProvider provider)
throws IOException
{
gen.writeStartObject(bean);
BeanPropertyWriter prop = null;
try {
switch (_propCount) {
default:
//case 6:
prop = _prop1;
prop.serializeAsField(bean, gen, provider);
// fall through
case 5:
prop = _prop2;
prop.serializeAsField(bean, gen, provider);
case 4:
prop = _prop3;
prop.serializeAsField(bean, gen, provider);
case 3:
prop = _prop4;
prop.serializeAsField(bean, gen, provider);
case 2:
prop = _prop5;
prop.serializeAsField(bean, gen, provider);
case 1:
prop = _prop6;
prop.serializeAsField(bean, gen, provider);
case 0:
}
prop = null;
if (_anyGetterWriter != null) {
_anyGetterWriter.getAndSerialize(bean, gen, provider);
}
} catch (Exception e) {
String name = (prop == null) ? "[anySetter]" : prop.getName();
wrapAndThrow(provider, e, bean, name);
} catch (StackOverflowError e) {
JsonMappingException mapE = new JsonMappingException(gen, "Infinite recursion (StackOverflowError)", e);
String name = (prop == null) ? "[anySetter]" : prop.getName();
mapE.prependPath(new JsonMappingException.Reference(bean, name));
throw mapE;
}
gen.writeEndObject();
}
}