1 package top.infra.jackson2.ser;
2
3 import com.fasterxml.jackson.core.JsonGenerator;
4 import com.fasterxml.jackson.databind.AnnotationIntrospector;
5 import com.fasterxml.jackson.databind.BeanProperty;
6 import com.fasterxml.jackson.databind.JavaType;
7 import com.fasterxml.jackson.databind.JsonMappingException;
8 import com.fasterxml.jackson.databind.JsonSerializer;
9 import com.fasterxml.jackson.databind.SerializerProvider;
10 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
11 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
12 import com.fasterxml.jackson.databind.ser.ContextualSerializer;
13 import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
14 import com.fasterxml.jackson.databind.ser.std.StdSerializer;
15
16 import org.apache.commons.lang3.tuple.Pair;
17
18 import java.io.IOException;
19 import java.util.Map;
20
21
22
23
24 public class PairSerializer extends StdSerializer<Pair<?, ?>> implements ContextualSerializer {
25
26
27
28
29 protected final BeanProperty _property;
30
31
32
33
34
35 protected final boolean _staticTyping;
36
37 protected final JavaType _entryType, _keyType, _valueType;
38
39
40
41 protected final TypeSerializer _kts;
42
43
44
45 protected final TypeSerializer _vts;
46
47
48
49 protected JsonSerializer<Object> _ks;
50
51
52
53 protected JsonSerializer<Object> _vs;
54
55
56
57
58 protected PropertySerializerMap _dks;
59
60
61
62
63 protected PropertySerializerMap _dvs;
64
65 public PairSerializer(
66 final JavaType type, final JavaType keyType, final JavaType valueType,
67 final boolean staticTyping,
68 final TypeSerializer kts, final TypeSerializer vts,
69 final BeanProperty property
70 ) {
71 super(type);
72 this._entryType = type;
73 this._keyType = keyType;
74 this._valueType = valueType;
75 this._staticTyping = staticTyping;
76 this._kts = kts;
77 this._vts = vts;
78 this._dks = PropertySerializerMap.emptyForProperties();
79 this._dvs = PropertySerializerMap.emptyForProperties();
80 this._property = property;
81 }
82
83 @SuppressWarnings("unchecked")
84 protected PairSerializer(
85 final PairSerializer src,
86 final BeanProperty property,
87 final TypeSerializer vts,
88 final JsonSerializer<?> keySer,
89 final JsonSerializer<?> valueSer
90 ) {
91 super(Map.class, false);
92 this._entryType = src._entryType;
93 this._keyType = src._keyType;
94 this._valueType = src._valueType;
95 this._staticTyping = src._staticTyping;
96 this._kts = src._kts;
97 this._vts = src._vts;
98 this._ks = (JsonSerializer<Object>) keySer;
99 this._vs = (JsonSerializer<Object>) valueSer;
100 this._dks = src._dks;
101 this._dvs = src._dvs;
102 this._property = src._property;
103 }
104
105 @Override
106 public JsonSerializer<?> createContextual(final SerializerProvider provider, final BeanProperty property) throws JsonMappingException {
107 JsonSerializer<?> vs = null;
108 JsonSerializer<?> ks = null;
109
110 final AnnotationIntrospector intr = provider.getAnnotationIntrospector();
111 final AnnotatedMember propertyAcc = (property == null) ? null : property.getMember();
112
113
114 if (propertyAcc != null && intr != null) {
115 Object serDef = intr.findKeySerializer(propertyAcc);
116 if (serDef != null) {
117 ks = provider.serializerInstance(propertyAcc, serDef);
118 }
119 serDef = intr.findContentSerializer(propertyAcc);
120 if (serDef != null) {
121 vs = provider.serializerInstance(propertyAcc, serDef);
122 }
123 }
124
125 if (vs == null) {
126 vs = this._vs;
127 }
128
129 vs = findConvertingContentSerializer(provider, property, vs);
130 if (vs == null) {
131
132
133
134 if (this._staticTyping && !this._valueType.isJavaLangObject()) {
135 vs = provider.findValueSerializer(this._valueType, property);
136 }
137 } else {
138 vs = provider.handleSecondaryContextualization(vs, property);
139 }
140
141 if (ks == null) {
142 ks = this._ks;
143 }
144 ks = findConvertingContentSerializer(provider, property, ks);
145 if (ks == null) {
146 if (this._staticTyping && !this._valueType.isJavaLangObject()) {
147 ks = provider.findValueSerializer(this._valueType, property);
148 }
149 } else {
150 ks = provider.handleSecondaryContextualization(ks, property);
151 }
152
153 PairSerializer mser = withResolved(property, ks, vs);
154
155 return mser;
156 }
157
158 public PairSerializer withResolved(BeanProperty property, JsonSerializer<?> ks, JsonSerializer<?> vs) {
159 return new PairSerializer(this, property, this._vts, ks, vs);
160 }
161
162 @Override
163 public void serialize(
164 final Pair<?, ?> value, final JsonGenerator gen, final SerializerProvider provider
165 ) throws IOException {
166 gen.writeStartObject(value);
167
168
169
170 serializeDynamic(value, gen, provider);
171
172 gen.writeEndObject();
173 }
174
175 @Override
176 public void serializeWithType(
177 final Pair<?, ?> value, final JsonGenerator gen, final SerializerProvider provider, final TypeSerializer typeSer
178 ) throws IOException {
179 typeSer.writeTypePrefixForObject(value, gen);
180
181 gen.setCurrentValue(value);
182
183
184
185 serializeDynamic(value, gen, provider);
186
187 typeSer.writeTypeSuffixForObject(value, gen);
188 }
189
190 protected void serializeDynamic(
191 final Pair<?, ?> value, final JsonGenerator jgen, final SerializerProvider provider
192 ) throws IOException {
193
194
195 final TypeSerializer vts = this._vts;
196 final TypeSerializer kts = this._kts;
197
198 PropertySerializerMap dvs = this._dvs;
199 PropertySerializerMap dks = this._dks;
200
201 Object valueElem = value.getValue();
202 Object keyElem = value.getKey();
203
204 jgen.writeFieldName("left");
205 if (keyElem == null) {
206 provider.defaultSerializeNull(jgen);
207 } else {
208 Class<?> cc = keyElem.getClass();
209 JsonSerializer<Object> ser = dks.serializerFor(cc);
210 if (ser == null) {
211 if (this._valueType.hasGenericTypes()) {
212 ser = _findAndAddDynamicKeySerializer(dks, provider.constructSpecializedType(this._keyType, cc), provider);
213 } else {
214 ser = _findAndAddDynamicKeySerializer(dks, cc, provider);
215 }
216 dks = this._dks;
217 }
218 try {
219 if (kts == null) {
220 ser.serialize(keyElem, jgen, provider);
221 } else {
222 ser.serializeWithType(keyElem, jgen, provider, kts);
223 }
224 } catch (final Exception e) {
225
226 String keyDesc = "" + keyElem;
227 wrapAndThrow(provider, e, value, keyDesc);
228 }
229 }
230
231
232 jgen.writeFieldName("right");
233 if (valueElem == null) {
234 provider.defaultSerializeNull(jgen);
235 } else {
236 Class<?> cc = valueElem.getClass();
237 JsonSerializer<Object> ser = dvs.serializerFor(cc);
238 if (ser == null) {
239 if (this._valueType.hasGenericTypes()) {
240 ser = _findAndAddDynamicValueSerializer(dvs, provider.constructSpecializedType(this._valueType, cc), provider);
241 } else {
242 ser = _findAndAddDynamicValueSerializer(dvs, cc, provider);
243 }
244 dvs = this._dvs;
245 }
246 try {
247 if (vts == null) {
248 ser.serialize(valueElem, jgen, provider);
249 } else {
250 ser.serializeWithType(valueElem, jgen, provider, vts);
251 }
252 } catch (final Exception e) {
253
254 String keyDesc = "" + keyElem;
255 wrapAndThrow(provider, e, value, keyDesc);
256 }
257 }
258 }
259
260
261 protected final JsonSerializer<Object> _findAndAddDynamicKeySerializer(
262 final PropertySerializerMap map,
263 final Class<?> type,
264 final SerializerProvider provider
265 ) throws JsonMappingException {
266 final PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, this._property);
267 if (map != result.map) {
268 this._dks = result.map;
269 }
270 return result.serializer;
271 }
272
273 protected final JsonSerializer<Object> _findAndAddDynamicKeySerializer(
274 final PropertySerializerMap map,
275 final JavaType type,
276 final SerializerProvider provider
277 ) throws JsonMappingException {
278 final PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, this._property);
279 if (map != result.map) {
280 this._dks = result.map;
281 }
282 return result.serializer;
283 }
284
285 protected final JsonSerializer<Object> _findAndAddDynamicValueSerializer(
286 final PropertySerializerMap map,
287 final Class<?> type,
288 final SerializerProvider provider
289 ) throws JsonMappingException {
290 final PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, this._property);
291 if (map != result.map) {
292 this._dvs = result.map;
293 }
294 return result.serializer;
295 }
296
297 protected final JsonSerializer<Object> _findAndAddDynamicValueSerializer(
298 final PropertySerializerMap map,
299 final JavaType type,
300 final SerializerProvider provider
301 ) throws JsonMappingException {
302 final PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSecondarySerializer(type, provider, this._property);
303 if (map != result.map) {
304 this._dvs = result.map;
305 }
306 return result.serializer;
307 }
308 }