1 package com.fasterxml.jackson.databind.ser.std;
2
3 import java.io.IOException;
4 import java.lang.reflect.InvocationTargetException;
5 import java.lang.reflect.Type;
6 import java.util.LinkedHashSet;
7 import java.util.Set;
8
9 import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
10 import com.fasterxml.jackson.core.*;
11 import com.fasterxml.jackson.core.type.WritableTypeId;
12 import com.fasterxml.jackson.databind.*;
13 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
14 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
15 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitable;
16 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
17 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonStringFormatVisitor;
18 import com.fasterxml.jackson.databind.jsonschema.SchemaAware;
19 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
20 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
21 import com.fasterxml.jackson.databind.ser.BeanSerializer;
22 import com.fasterxml.jackson.databind.ser.ContextualSerializer;
23 import com.fasterxml.jackson.databind.util.ClassUtil;
24
25
37 @SuppressWarnings("serial")
38 @JacksonStdImpl
39 public class JsonValueSerializer
40 extends StdSerializer<Object>
41 implements ContextualSerializer, JsonFormatVisitable, SchemaAware
42 {
43
46 protected final AnnotatedMember _accessor;
47
48 protected final JsonSerializer<Object> _valueSerializer;
49
50 protected final BeanProperty _property;
51
52
58 protected final boolean _forceTypeInformation;
59
60
65
66
75 @SuppressWarnings("unchecked")
76 public JsonValueSerializer(AnnotatedMember accessor, JsonSerializer<?> ser)
77 {
78 super(accessor.getType());
79 _accessor = accessor;
80 _valueSerializer = (JsonSerializer<Object>) ser;
81 _property = null;
82 _forceTypeInformation = true;
83 }
84
85 @SuppressWarnings("unchecked")
86 public JsonValueSerializer(JsonValueSerializer src, BeanProperty property,
87 JsonSerializer<?> ser, boolean forceTypeInfo)
88 {
89 super(_notNullClass(src.handledType()));
90 _accessor = src._accessor;
91 _valueSerializer = (JsonSerializer<Object>) ser;
92 _property = property;
93 _forceTypeInformation = forceTypeInfo;
94 }
95
96 @SuppressWarnings("unchecked")
97 private final static Class<Object> _notNullClass(Class<?> cls) {
98 return (cls == null) ? Object.class : (Class<Object>) cls;
99 }
100
101 public JsonValueSerializer withResolved(BeanProperty property,
102 JsonSerializer<?> ser, boolean forceTypeInfo)
103 {
104 if (_property == property && _valueSerializer == ser
105 && forceTypeInfo == _forceTypeInformation) {
106 return this;
107 }
108 return new JsonValueSerializer(this, property, ser, forceTypeInfo);
109 }
110
111
116
117
121 @Override
122 public JsonSerializer<?> createContextual(SerializerProvider provider,
123 BeanProperty property)
124 throws JsonMappingException
125 {
126 JsonSerializer<?> ser = _valueSerializer;
127 if (ser == null) {
128
129
130
131
132 JavaType t = _accessor.getType();
133 if (provider.isEnabled(MapperFeature.USE_STATIC_TYPING) || t.isFinal()) {
134
135
139
140 ser = provider.findPrimaryPropertySerializer(t, property);
141
145 boolean forceTypeInformation = isNaturalTypeWithStdHandling(t.getRawClass(), ser);
146 return withResolved(property, ser, forceTypeInformation);
147 }
148
149 if (property != _property) {
150 return withResolved(property, ser, _forceTypeInformation);
151 }
152 } else {
153
154 ser = provider.handlePrimaryContextualization(ser, property);
155 return withResolved(property, ser, _forceTypeInformation);
156 }
157 return this;
158 }
159
160
165
166 @Override
167 public void serialize(Object bean, JsonGenerator gen, SerializerProvider prov) throws IOException
168 {
169 try {
170 Object value = _accessor.getValue(bean);
171 if (value == null) {
172 prov.defaultSerializeNull(gen);
173 return;
174 }
175 JsonSerializer<Object> ser = _valueSerializer;
176 if (ser == null) {
177 Class<?> c = value.getClass();
178
179
180
181
182
183 ser = prov.findTypedValueSerializer(c, true, _property);
184 }
185 ser.serialize(value, gen, prov);
186 } catch (Exception e) {
187 wrapAndThrow(prov, e, bean, _accessor.getName() + "()");
188 }
189 }
190
191 @Override
192 public void serializeWithType(Object bean, JsonGenerator gen, SerializerProvider provider,
193 TypeSerializer typeSer0) throws IOException
194 {
195
196 Object value = null;
197 try {
198 value = _accessor.getValue(bean);
199
200 if (value == null) {
201 provider.defaultSerializeNull(gen);
202 return;
203 }
204 JsonSerializer<Object> ser = _valueSerializer;
205 if (ser == null) {
206 ser = provider.findValueSerializer(value.getClass(), _property);
207 } else {
208
209
210 if (_forceTypeInformation) {
211
212 WritableTypeId typeIdDef = typeSer0.writeTypePrefix(gen,
213 typeSer0.typeId(bean, JsonToken.VALUE_STRING));
214 ser.serialize(value, gen, provider);
215 typeSer0.writeTypeSuffix(gen, typeIdDef);
216
217 return;
218 }
219 }
220
221
222
223 TypeSerializerRerouter rr = new TypeSerializerRerouter(typeSer0, bean);
224 ser.serializeWithType(value, gen, provider, rr);
225 } catch (Exception e) {
226 wrapAndThrow(provider, e, bean, _accessor.getName() + "()");
227 }
228 }
229
230 @SuppressWarnings("deprecation")
231 @Override
232 public JsonNode getSchema(SerializerProvider provider, Type typeHint)
233 throws JsonMappingException
234 {
235 if (_valueSerializer instanceof SchemaAware) {
236 return ((SchemaAware)_valueSerializer).getSchema(provider, null);
237 }
238 return com.fasterxml.jackson.databind.jsonschema.JsonSchema.getDefaultSchemaNode();
239 }
240
241 @Override
242 public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
243 throws JsonMappingException
244 {
245
254 final JavaType type = _accessor.getType();
255 Class<?> declaring = _accessor.getDeclaringClass();
256 if ((declaring != null) && ClassUtil.isEnumType(declaring)) {
257 if (_acceptJsonFormatVisitorForEnum(visitor, typeHint, declaring)) {
258 return;
259 }
260 }
261 JsonSerializer<Object> ser = _valueSerializer;
262 if (ser == null) {
263 ser = visitor.getProvider().findTypedValueSerializer(type, false, _property);
264 if (ser == null) {
265 visitor.expectAnyFormat(typeHint);
266 return;
267 }
268 }
269 ser.acceptJsonFormatVisitor(visitor, type);
270 }
271
272
281 protected boolean _acceptJsonFormatVisitorForEnum(JsonFormatVisitorWrapper visitor,
282 JavaType typeHint, Class<?> enumType)
283 throws JsonMappingException
284 {
285
286 JsonStringFormatVisitor stringVisitor = visitor.expectStringFormat(typeHint);
287 if (stringVisitor != null) {
288 Set<String> enums = new LinkedHashSet<String>();
289 for (Object en : enumType.getEnumConstants()) {
290 try {
291
292
293
294 enums.add(String.valueOf(_accessor.getValue(en)));
295 } catch (Exception e) {
296 Throwable t = e;
297 while (t instanceof InvocationTargetException && t.getCause() != null) {
298 t = t.getCause();
299 }
300 ClassUtil.throwIfError(t);
301 throw JsonMappingException.wrapWithPath(t, en, _accessor.getName() + "()");
302 }
303 }
304 stringVisitor.enumTypes(enums);
305 }
306 return true;
307 }
308
309 protected boolean isNaturalTypeWithStdHandling(Class<?> rawType, JsonSerializer<?> ser)
310 {
311
312 if (rawType.isPrimitive()) {
313 if (rawType != Integer.TYPE && rawType != Boolean.TYPE && rawType != Double.TYPE) {
314 return false;
315 }
316 } else {
317 if (rawType != String.class &&
318 rawType != Integer.class && rawType != Boolean.class && rawType != Double.class) {
319 return false;
320 }
321 }
322 return isDefaultSerializer(ser);
323 }
324
325
330
331 @Override
332 public String toString() {
333 return "(@JsonValue serializer for method " + _accessor.getDeclaringClass() + "#" + _accessor.getName() + ")";
334 }
335
336
341
342
347 static class TypeSerializerRerouter
348 extends TypeSerializer
349 {
350 protected final TypeSerializer _typeSerializer;
351 protected final Object _forObject;
352
353 public TypeSerializerRerouter(TypeSerializer ts, Object ob) {
354 _typeSerializer = ts;
355 _forObject = ob;
356 }
357
358 @Override
359 public TypeSerializer forProperty(BeanProperty prop) {
360 throw new UnsupportedOperationException();
361 }
362
363 @Override
364 public As getTypeInclusion() {
365 return _typeSerializer.getTypeInclusion();
366 }
367
368 @Override
369 public String getPropertyName() {
370 return _typeSerializer.getPropertyName();
371 }
372
373 @Override
374 public TypeIdResolver getTypeIdResolver() {
375 return _typeSerializer.getTypeIdResolver();
376 }
377
378
379
380 @Override
381 public WritableTypeId writeTypePrefix(JsonGenerator g,
382 WritableTypeId typeId) throws IOException {
383
384 typeId.forValue = _forObject;
385 return _typeSerializer.writeTypePrefix(g, typeId);
386 }
387
388 @Override
389 public WritableTypeId writeTypeSuffix(JsonGenerator g,
390 WritableTypeId typeId) throws IOException {
391
392 return _typeSerializer.writeTypeSuffix(g, typeId);
393 }
394
395
396
397 @Override
398 @Deprecated
399 public void writeTypePrefixForScalar(Object value, JsonGenerator gen) throws IOException {
400 _typeSerializer.writeTypePrefixForScalar(_forObject, gen);
401 }
402
403 @Override
404 @Deprecated
405 public void writeTypePrefixForObject(Object value, JsonGenerator gen) throws IOException {
406 _typeSerializer.writeTypePrefixForObject(_forObject, gen);
407 }
408
409 @Override
410 @Deprecated
411 public void writeTypePrefixForArray(Object value, JsonGenerator gen) throws IOException {
412 _typeSerializer.writeTypePrefixForArray(_forObject, gen);
413 }
414
415 @Override
416 @Deprecated
417 public void writeTypeSuffixForScalar(Object value, JsonGenerator gen) throws IOException {
418 _typeSerializer.writeTypeSuffixForScalar(_forObject, gen);
419 }
420
421 @Override
422 @Deprecated
423 public void writeTypeSuffixForObject(Object value, JsonGenerator gen) throws IOException {
424 _typeSerializer.writeTypeSuffixForObject(_forObject, gen);
425 }
426
427 @Override
428 @Deprecated
429 public void writeTypeSuffixForArray(Object value, JsonGenerator gen) throws IOException {
430 _typeSerializer.writeTypeSuffixForArray(_forObject, gen);
431 }
432
433 @Override
434 @Deprecated
435 public void writeTypePrefixForScalar(Object value, JsonGenerator gen, Class<?> type) throws IOException {
436 _typeSerializer.writeTypePrefixForScalar(_forObject, gen, type);
437 }
438
439 @Override
440 @Deprecated
441 public void writeTypePrefixForObject(Object value, JsonGenerator gen, Class<?> type) throws IOException {
442 _typeSerializer.writeTypePrefixForObject(_forObject, gen, type);
443 }
444
445 @Override
446 @Deprecated
447 public void writeTypePrefixForArray(Object value, JsonGenerator gen, Class<?> type) throws IOException {
448 _typeSerializer.writeTypePrefixForArray(_forObject, gen, type);
449 }
450
451
456
457 @Override
458 @Deprecated
459 public void writeCustomTypePrefixForScalar(Object value, JsonGenerator gen, String typeId)
460 throws IOException {
461 _typeSerializer.writeCustomTypePrefixForScalar(_forObject, gen, typeId);
462 }
463
464 @Override
465 @Deprecated
466 public void writeCustomTypePrefixForObject(Object value, JsonGenerator gen, String typeId) throws IOException {
467 _typeSerializer.writeCustomTypePrefixForObject(_forObject, gen, typeId);
468 }
469
470 @Override
471 @Deprecated
472 public void writeCustomTypePrefixForArray(Object value, JsonGenerator gen, String typeId) throws IOException {
473 _typeSerializer.writeCustomTypePrefixForArray(_forObject, gen, typeId);
474 }
475
476 @Override
477 @Deprecated
478 public void writeCustomTypeSuffixForScalar(Object value, JsonGenerator gen, String typeId) throws IOException {
479 _typeSerializer.writeCustomTypeSuffixForScalar(_forObject, gen, typeId);
480 }
481
482 @Override
483 @Deprecated
484 public void writeCustomTypeSuffixForObject(Object value, JsonGenerator gen, String typeId) throws IOException {
485 _typeSerializer.writeCustomTypeSuffixForObject(_forObject, gen, typeId);
486 }
487
488 @Override
489 @Deprecated
490 public void writeCustomTypeSuffixForArray(Object value, JsonGenerator gen, String typeId) throws IOException {
491 _typeSerializer.writeCustomTypeSuffixForArray(_forObject, gen, typeId);
492 }
493 }
494 }
495