1 package com.fasterxml.jackson.databind.introspect;
2
3 import java.lang.annotation.Annotation;
4 import java.lang.reflect.Field;
5 import java.util.*;
6
7 import com.fasterxml.jackson.annotation.*;
8 import com.fasterxml.jackson.core.Version;
9 import com.fasterxml.jackson.databind.*;
10 import com.fasterxml.jackson.databind.annotation.*;
11 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
12 import com.fasterxml.jackson.databind.cfg.MapperConfig;
13 import com.fasterxml.jackson.databind.ext.Java7Support;
14 import com.fasterxml.jackson.databind.jsontype.NamedType;
15 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
16 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
17 import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
18 import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
19 import com.fasterxml.jackson.databind.ser.VirtualBeanPropertyWriter;
20 import com.fasterxml.jackson.databind.ser.impl.AttributePropertyWriter;
21 import com.fasterxml.jackson.databind.ser.std.RawSerializer;
22 import com.fasterxml.jackson.databind.type.MapLikeType;
23 import com.fasterxml.jackson.databind.type.TypeFactory;
24 import com.fasterxml.jackson.databind.util.*;
25
26
30 public class JacksonAnnotationIntrospector
31 extends AnnotationIntrospector
32 implements java.io.Serializable
33 {
34 private static final long serialVersionUID = 1L;
35
36 @SuppressWarnings("unchecked")
37 private final static Class<? extends Annotation>[] ANNOTATIONS_TO_INFER_SER = (Class<? extends Annotation>[])
38 new Class<?>[] {
39 JsonSerialize.class,
40 JsonView.class,
41 JsonFormat.class,
42 JsonTypeInfo.class,
43 JsonRawValue.class,
44 JsonUnwrapped.class,
45 JsonBackReference.class,
46 JsonManagedReference.class
47 };
48
49 @SuppressWarnings("unchecked")
50 private final static Class<? extends Annotation>[] ANNOTATIONS_TO_INFER_DESER = (Class<? extends Annotation>[])
51 new Class<?>[] {
52 JsonDeserialize.class,
53 JsonView.class,
54 JsonFormat.class,
55 JsonTypeInfo.class,
56 JsonUnwrapped.class,
57 JsonBackReference.class,
58 JsonManagedReference.class,
59 JsonMerge.class
60 };
61
62
63
64 private static final Java7Support _java7Helper;
65 static {
66 Java7Support x = null;
67 try {
68 x = Java7Support.instance();
69 } catch (Throwable t) { }
70 _java7Helper = x;
71 }
72
73
82 protected transient LRUMap<Class<?>,Boolean> _annotationsInside = new LRUMap<Class<?>,Boolean>(48, 48);
83
84
89
90
98 protected boolean _cfgConstructorPropertiesImpliesCreator = true;
99
100
105
106 public JacksonAnnotationIntrospector() { }
107
108 @Override
109 public Version version() {
110 return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION;
111 }
112
113 protected Object readResolve() {
114 if (_annotationsInside == null) {
115 _annotationsInside = new LRUMap<Class<?>,Boolean>(48, 48);
116 }
117 return this;
118 }
119
120
125
126
136 public JacksonAnnotationIntrospector setConstructorPropertiesImpliesCreator(boolean b)
137 {
138 _cfgConstructorPropertiesImpliesCreator = b;
139 return this;
140 }
141
142
147
148
152 @Override
153 public boolean isAnnotationBundle(Annotation ann) {
154
155
156
157
158 Class<?> type = ann.annotationType();
159 Boolean b = _annotationsInside.get(type);
160 if (b == null) {
161 b = type.getAnnotation(JacksonAnnotationsInside.class) != null;
162 _annotationsInside.putIfAbsent(type, b);
163 }
164 return b.booleanValue();
165 }
166
167
172
173
177 @Override
178 @Deprecated
179 public String findEnumValue(Enum<?> value)
180 {
181
182
183
184 try {
185
186 Field f = value.getClass().getField(value.name());
187 if (f != null) {
188 JsonProperty prop = f.getAnnotation(JsonProperty.class);
189 if (prop != null) {
190 String n = prop.value();
191 if (n != null && !n.isEmpty()) {
192 return n;
193 }
194 }
195 }
196 } catch (SecurityException e) {
197
198 } catch (NoSuchFieldException e) {
199
200 }
201 return value.name();
202 }
203
204 @Override
205 public String[] findEnumValues(Class<?> enumType, Enum<?>[] enumValues, String[] names) {
206 HashMap<String,String> expl = null;
207 for (Field f : enumType.getDeclaredFields()) {
208 if (!f.isEnumConstant()) {
209 continue;
210 }
211 JsonProperty prop = f.getAnnotation(JsonProperty.class);
212 if (prop == null) {
213 continue;
214 }
215 String n = prop.value();
216 if (n.isEmpty()) {
217 continue;
218 }
219 if (expl == null) {
220 expl = new HashMap<String,String>();
221 }
222 expl.put(f.getName(), n);
223 }
224
225 if (expl != null) {
226 for (int i = 0, end = enumValues.length; i < end; ++i) {
227 String defName = enumValues[i].name();
228 String explValue = expl.get(defName);
229 if (explValue != null) {
230 names[i] = explValue;
231 }
232 }
233 }
234 return names;
235 }
236
237 @Override
238 public void findEnumAliases(Class<?> enumType, Enum<?>[] enumValues, String[][] aliasList)
239 {
240
241
242 for (Field f : enumType.getDeclaredFields()) {
243 if (f.isEnumConstant()) {
244 JsonAlias aliasAnnotation = f.getAnnotation(JsonAlias.class);
245 if (aliasAnnotation != null) {
246 String[] aliases = aliasAnnotation.value();
247 if (aliases.length != 0) {
248 final String name = f.getName();
249
250 for (int i = 0, end = enumValues.length; i < end; ++i) {
251 if (name.equals(enumValues[i].name())) {
252 aliasList[i] = aliases;
253 }
254 }
255 }
256 }
257 }
258 }
259 }
260
261
270 @Override
271 public Enum<?> findDefaultEnumValue(Class<Enum<?>> enumCls) {
272 return ClassUtil.findFirstAnnotatedEnumValue(enumCls, JsonEnumDefaultValue.class);
273 }
274
275
280
281 @Override
282 public PropertyName findRootName(AnnotatedClass ac)
283 {
284 JsonRootName ann = _findAnnotation(ac, JsonRootName.class);
285 if (ann == null) {
286 return null;
287 }
288 String ns = ann.namespace();
289 if (ns != null && ns.length() == 0) {
290 ns = null;
291 }
292 return PropertyName.construct(ann.value(), ns);
293 }
294
295 @Override
296 public JsonIgnoreProperties.Value findPropertyIgnorals(Annotated a)
297 {
298 JsonIgnoreProperties v = _findAnnotation(a, JsonIgnoreProperties.class);
299 if (v == null) {
300 return JsonIgnoreProperties.Value.empty();
301 }
302 return JsonIgnoreProperties.Value.from(v);
303 }
304
305 @Override
306 public Boolean isIgnorableType(AnnotatedClass ac) {
307 JsonIgnoreType ignore = _findAnnotation(ac, JsonIgnoreType.class);
308 return (ignore == null) ? null : ignore.value();
309 }
310
311 @Override
312 public Object findFilterId(Annotated a) {
313 JsonFilter ann = _findAnnotation(a, JsonFilter.class);
314 if (ann != null) {
315 String id = ann.value();
316
317 if (id.length() > 0) {
318 return id;
319 }
320 }
321 return null;
322 }
323
324 @Override
325 public Object findNamingStrategy(AnnotatedClass ac)
326 {
327 JsonNaming ann = _findAnnotation(ac, JsonNaming.class);
328 return (ann == null) ? null : ann.value();
329 }
330
331 @Override
332 public String findClassDescription(AnnotatedClass ac) {
333 JsonClassDescription ann = _findAnnotation(ac, JsonClassDescription.class);
334 return (ann == null) ? null : ann.value();
335 }
336
337
342
343 @Override
344 public VisibilityChecker<?> findAutoDetectVisibility(AnnotatedClass ac,
345 VisibilityChecker<?> checker)
346 {
347 JsonAutoDetect ann = _findAnnotation(ac, JsonAutoDetect.class);
348 return (ann == null) ? checker : checker.with(ann);
349 }
350
351
356
357 @Override
358 public String findImplicitPropertyName(AnnotatedMember m) {
359 PropertyName n = _findConstructorName(m);
360 return (n == null) ? null : n.getSimpleName();
361 }
362
363 @Override
364 public List<PropertyName> findPropertyAliases(Annotated m) {
365 JsonAlias ann = _findAnnotation(m, JsonAlias.class);
366 if (ann == null) {
367 return null;
368 }
369 String[] strs = ann.value();
370 final int len = strs.length;
371 if (len == 0) {
372 return Collections.emptyList();
373 }
374 List<PropertyName> result = new ArrayList<>(len);
375 for (int i = 0; i < len; ++i) {
376 result.add(PropertyName.construct(strs[i]));
377 }
378 return result;
379 }
380
381 @Override
382 public boolean hasIgnoreMarker(AnnotatedMember m) {
383 return _isIgnorable(m);
384 }
385
386 @Override
387 public Boolean hasRequiredMarker(AnnotatedMember m)
388 {
389 JsonProperty ann = _findAnnotation(m, JsonProperty.class);
390 if (ann != null) {
391 return ann.required();
392 }
393 return null;
394 }
395
396 @Override
397 public JsonProperty.Access findPropertyAccess(Annotated m) {
398 JsonProperty ann = _findAnnotation(m, JsonProperty.class);
399 if (ann != null) {
400 return ann.access();
401 }
402 return null;
403 }
404
405 @Override
406 public String findPropertyDescription(Annotated ann) {
407 JsonPropertyDescription desc = _findAnnotation(ann, JsonPropertyDescription.class);
408 return (desc == null) ? null : desc.value();
409 }
410
411 @Override
412 public Integer findPropertyIndex(Annotated ann) {
413 JsonProperty prop = _findAnnotation(ann, JsonProperty.class);
414 if (prop != null) {
415 int ix = prop.index();
416 if (ix != JsonProperty.INDEX_UNKNOWN) {
417 return Integer.valueOf(ix);
418 }
419 }
420 return null;
421 }
422
423 @Override
424 public String findPropertyDefaultValue(Annotated ann) {
425 JsonProperty prop = _findAnnotation(ann, JsonProperty.class);
426 if (prop == null) {
427 return null;
428 }
429 String str = prop.defaultValue();
430
431 return str.isEmpty() ? null : str;
432 }
433
434 @Override
435 public JsonFormat.Value findFormat(Annotated ann) {
436 JsonFormat f = _findAnnotation(ann, JsonFormat.class);
437
438
439 return (f == null) ? null : JsonFormat.Value.from(f);
440 }
441
442 @Override
443 public ReferenceProperty findReferenceType(AnnotatedMember member)
444 {
445 JsonManagedReference ref1 = _findAnnotation(member, JsonManagedReference.class);
446 if (ref1 != null) {
447 return AnnotationIntrospector.ReferenceProperty.managed(ref1.value());
448 }
449 JsonBackReference ref2 = _findAnnotation(member, JsonBackReference.class);
450 if (ref2 != null) {
451 return AnnotationIntrospector.ReferenceProperty.back(ref2.value());
452 }
453 return null;
454 }
455
456 @Override
457 public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member)
458 {
459 JsonUnwrapped ann = _findAnnotation(member, JsonUnwrapped.class);
460
461
462 if (ann == null || !ann.enabled()) {
463 return null;
464 }
465 String prefix = ann.prefix();
466 String suffix = ann.suffix();
467 return NameTransformer.simpleTransformer(prefix, suffix);
468 }
469
470 @Override
471 public JacksonInject.Value findInjectableValue(AnnotatedMember m) {
472 JacksonInject ann = _findAnnotation(m, JacksonInject.class);
473 if (ann == null) {
474 return null;
475 }
476
477 JacksonInject.Value v = JacksonInject.Value.from(ann);
478 if (!v.hasId()) {
479 Object id;
480
481 if (!(m instanceof AnnotatedMethod)) {
482 id = m.getRawType().getName();
483 } else {
484 AnnotatedMethod am = (AnnotatedMethod) m;
485 if (am.getParameterCount() == 0) {
486 id = m.getRawType().getName();
487 } else {
488 id = am.getRawParameterType(0).getName();
489 }
490 }
491 v = v.withId(id);
492 }
493 return v;
494 }
495
496 @Override
497 @Deprecated
498 public Object findInjectableValueId(AnnotatedMember m) {
499 JacksonInject.Value v = findInjectableValue(m);
500 return (v == null) ? null : v.getId();
501 }
502
503 @Override
504 public Class<?>[] findViews(Annotated a)
505 {
506 JsonView ann = _findAnnotation(a, JsonView.class);
507 return (ann == null) ? null : ann.value();
508 }
509
510 @Override
511 public AnnotatedMethod resolveSetterConflict(MapperConfig<?> config,
512 AnnotatedMethod setter1, AnnotatedMethod setter2)
513 {
514 Class<?> cls1 = setter1.getRawParameterType(0);
515 Class<?> cls2 = setter2.getRawParameterType(0);
516
517
518
519 if (cls1.isPrimitive()) {
520 if (!cls2.isPrimitive()) {
521 return setter1;
522 }
523 } else if (cls2.isPrimitive()) {
524 return setter2;
525 }
526
527 if (cls1 == String.class) {
528 if (cls2 != String.class) {
529 return setter1;
530 }
531 } else if (cls2 == String.class) {
532 return setter2;
533 }
534
535 return null;
536 }
537
538 @Override
539 public PropertyName findRenameByField(MapperConfig<?> config,
540 AnnotatedField f, PropertyName implName) {
541
542 return null;
543 }
544
545
550
551 @Override
552 public TypeResolverBuilder<?> findTypeResolver(MapperConfig<?> config,
553 AnnotatedClass ac, JavaType baseType)
554 {
555 return _findTypeResolver(config, ac, baseType);
556 }
557
558 @Override
559 public TypeResolverBuilder<?> findPropertyTypeResolver(MapperConfig<?> config,
560 AnnotatedMember am, JavaType baseType)
561 {
562
565
566 if (baseType.isContainerType() || baseType.isReferenceType()) {
567 return null;
568 }
569
570 return _findTypeResolver(config, am, baseType);
571 }
572
573 @Override
574 public TypeResolverBuilder<?> findPropertyContentTypeResolver(MapperConfig<?> config,
575 AnnotatedMember am, JavaType containerType)
576 {
577
580 if (containerType.getContentType() == null) {
581 throw new IllegalArgumentException("Must call method with a container or reference type (got "+containerType+")");
582 }
583 return _findTypeResolver(config, am, containerType);
584 }
585
586 @Override
587 public List<NamedType> findSubtypes(Annotated a)
588 {
589 JsonSubTypes t = _findAnnotation(a, JsonSubTypes.class);
590 if (t == null) return null;
591 JsonSubTypes.Type[] types = t.value();
592 ArrayList<NamedType> result = new ArrayList<NamedType>(types.length);
593 for (JsonSubTypes.Type type : types) {
594 result.add(new NamedType(type.value(), type.name()));
595 }
596 return result;
597 }
598
599 @Override
600 public String findTypeName(AnnotatedClass ac)
601 {
602 JsonTypeName tn = _findAnnotation(ac, JsonTypeName.class);
603 return (tn == null) ? null : tn.value();
604 }
605
606 @Override
607 public Boolean isTypeId(AnnotatedMember member) {
608 return _hasAnnotation(member, JsonTypeId.class);
609 }
610
611
616
617 @Override
618 public ObjectIdInfo findObjectIdInfo(Annotated ann) {
619 JsonIdentityInfo info = _findAnnotation(ann, JsonIdentityInfo.class);
620 if (info == null || info.generator() == ObjectIdGenerators.None.class) {
621 return null;
622 }
623
624 PropertyName name = PropertyName.construct(info.property());
625 return new ObjectIdInfo(name, info.scope(), info.generator(), info.resolver());
626 }
627
628 @Override
629 public ObjectIdInfo findObjectReferenceInfo(Annotated ann, ObjectIdInfo objectIdInfo) {
630 JsonIdentityReference ref = _findAnnotation(ann, JsonIdentityReference.class);
631 if (ref == null) {
632 return objectIdInfo;
633 }
634 if (objectIdInfo == null) {
635 objectIdInfo = ObjectIdInfo.empty();
636 }
637 return objectIdInfo.withAlwaysAsId(ref.alwaysAsId());
638 }
639
640
645
646 @Override
647 public Object findSerializer(Annotated a)
648 {
649 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
650 if (ann != null) {
651 @SuppressWarnings("rawtypes")
652 Class<? extends JsonSerializer> serClass = ann.using();
653 if (serClass != JsonSerializer.None.class) {
654 return serClass;
655 }
656 }
657
658
662 JsonRawValue annRaw = _findAnnotation(a, JsonRawValue.class);
663 if ((annRaw != null) && annRaw.value()) {
664
665 Class<?> cls = a.getRawType();
666 return new RawSerializer<Object>(cls);
667 }
668 return null;
669 }
670
671 @Override
672 public Object findKeySerializer(Annotated a)
673 {
674 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
675 if (ann != null) {
676 @SuppressWarnings("rawtypes")
677 Class<? extends JsonSerializer> serClass = ann.keyUsing();
678 if (serClass != JsonSerializer.None.class) {
679 return serClass;
680 }
681 }
682 return null;
683 }
684
685 @Override
686 public Object findContentSerializer(Annotated a)
687 {
688 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
689 if (ann != null) {
690 @SuppressWarnings("rawtypes")
691 Class<? extends JsonSerializer> serClass = ann.contentUsing();
692 if (serClass != JsonSerializer.None.class) {
693 return serClass;
694 }
695 }
696 return null;
697 }
698
699 @Override
700 public Object findNullSerializer(Annotated a)
701 {
702 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
703 if (ann != null) {
704 @SuppressWarnings("rawtypes")
705 Class<? extends JsonSerializer> serClass = ann.nullsUsing();
706 if (serClass != JsonSerializer.None.class) {
707 return serClass;
708 }
709 }
710 return null;
711 }
712
713 @Override
714 public JsonInclude.Value findPropertyInclusion(Annotated a)
715 {
716 JsonInclude inc = _findAnnotation(a, JsonInclude.class);
717 JsonInclude.Value value = (inc == null) ? JsonInclude.Value.empty() : JsonInclude.Value.from(inc);
718
719
720 if (value.getValueInclusion() == JsonInclude.Include.USE_DEFAULTS) {
721 value = _refinePropertyInclusion(a, value);
722 }
723 return value;
724 }
725
726 @SuppressWarnings("deprecation")
727 private JsonInclude.Value _refinePropertyInclusion(Annotated a, JsonInclude.Value value) {
728 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
729 if (ann != null) {
730 switch (ann.include()) {
731 case ALWAYS:
732 return value.withValueInclusion(JsonInclude.Include.ALWAYS);
733 case NON_NULL:
734 return value.withValueInclusion(JsonInclude.Include.NON_NULL);
735 case NON_DEFAULT:
736 return value.withValueInclusion(JsonInclude.Include.NON_DEFAULT);
737 case NON_EMPTY:
738 return value.withValueInclusion(JsonInclude.Include.NON_EMPTY);
739 case DEFAULT_INCLUSION:
740 default:
741 }
742 }
743 return value;
744 }
745
746 @Override
747 public JsonSerialize.Typing findSerializationTyping(Annotated a)
748 {
749 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
750 return (ann == null) ? null : ann.typing();
751 }
752
753 @Override
754 public Object findSerializationConverter(Annotated a) {
755 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
756 return (ann == null) ? null : _classIfExplicit(ann.converter(), Converter.None.class);
757 }
758
759 @Override
760 public Object findSerializationContentConverter(AnnotatedMember a) {
761 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class);
762 return (ann == null) ? null : _classIfExplicit(ann.contentConverter(), Converter.None.class);
763 }
764
765
770
771 @Override
772 public JavaType refineSerializationType(final MapperConfig<?> config,
773 final Annotated a, final JavaType baseType) throws JsonMappingException
774 {
775 JavaType type = baseType;
776 final TypeFactory tf = config.getTypeFactory();
777
778 final JsonSerialize jsonSer = _findAnnotation(a, JsonSerialize.class);
779
780
781
782 final Class<?> serClass = (jsonSer == null) ? null : _classIfExplicit(jsonSer.as());
783 if (serClass != null) {
784 if (type.hasRawClass(serClass)) {
785
786
787 type = type.withStaticTyping();
788 } else {
789 Class<?> currRaw = type.getRawClass();
790 try {
791
792
793 if (serClass.isAssignableFrom(currRaw)) {
794 type = tf.constructGeneralizedType(type, serClass);
795 } else if (currRaw.isAssignableFrom(serClass)) {
796 type = tf.constructSpecializedType(type, serClass);
797 } else if (_primitiveAndWrapper(currRaw, serClass)) {
798
799 type = type.withStaticTyping();
800 } else {
801 throw new JsonMappingException(null,
802 String.format("Cannot refine serialization type %s into %s; types not related",
803 type, serClass.getName()));
804 }
805 } catch (IllegalArgumentException iae) {
806 throw new JsonMappingException(null,
807 String.format("Failed to widen type %s with annotation (value %s), from '%s': %s",
808 type, serClass.getName(), a.getName(), iae.getMessage()),
809 iae);
810 }
811 }
812 }
813
814
815
816 if (type.isMapLikeType()) {
817 JavaType keyType = type.getKeyType();
818 final Class<?> keyClass = (jsonSer == null) ? null : _classIfExplicit(jsonSer.keyAs());
819 if (keyClass != null) {
820 if (keyType.hasRawClass(keyClass)) {
821 keyType = keyType.withStaticTyping();
822 } else {
823 Class<?> currRaw = keyType.getRawClass();
824 try {
825
826
827
828 if (keyClass.isAssignableFrom(currRaw)) {
829 keyType = tf.constructGeneralizedType(keyType, keyClass);
830 } else if (currRaw.isAssignableFrom(keyClass)) {
831 keyType = tf.constructSpecializedType(keyType, keyClass);
832 } else if (_primitiveAndWrapper(currRaw, keyClass)) {
833
834 keyType = keyType.withStaticTyping();
835 } else {
836 throw new JsonMappingException(null,
837 String.format("Cannot refine serialization key type %s into %s; types not related",
838 keyType, keyClass.getName()));
839 }
840 } catch (IllegalArgumentException iae) {
841 throw new JsonMappingException(null,
842 String.format("Failed to widen key type of %s with concrete-type annotation (value %s), from '%s': %s",
843 type, keyClass.getName(), a.getName(), iae.getMessage()),
844 iae);
845 }
846 }
847 type = ((MapLikeType) type).withKeyType(keyType);
848 }
849 }
850
851 JavaType contentType = type.getContentType();
852 if (contentType != null) {
853
854 final Class<?> contentClass = (jsonSer == null) ? null : _classIfExplicit(jsonSer.contentAs());
855 if (contentClass != null) {
856 if (contentType.hasRawClass(contentClass)) {
857 contentType = contentType.withStaticTyping();
858 } else {
859
860
861
862 Class<?> currRaw = contentType.getRawClass();
863 try {
864 if (contentClass.isAssignableFrom(currRaw)) {
865 contentType = tf.constructGeneralizedType(contentType, contentClass);
866 } else if (currRaw.isAssignableFrom(contentClass)) {
867 contentType = tf.constructSpecializedType(contentType, contentClass);
868 } else if (_primitiveAndWrapper(currRaw, contentClass)) {
869
870 contentType = contentType.withStaticTyping();
871 } else {
872 throw new JsonMappingException(null,
873 String.format("Cannot refine serialization content type %s into %s; types not related",
874 contentType, contentClass.getName()));
875 }
876 } catch (IllegalArgumentException iae) {
877 throw new JsonMappingException(null,
878 String.format("Internal error: failed to refine value type of %s with concrete-type annotation (value %s), from '%s': %s",
879 type, contentClass.getName(), a.getName(), iae.getMessage()),
880 iae);
881 }
882 }
883 type = type.withContentType(contentType);
884 }
885 }
886 return type;
887 }
888
889 @Override
890 @Deprecated
891 public Class<?> findSerializationType(Annotated am) {
892 return null;
893 }
894
895 @Override
896 @Deprecated
897 public Class<?> findSerializationKeyType(Annotated am, JavaType baseType) {
898 return null;
899 }
900
901 @Override
902 @Deprecated
903 public Class<?> findSerializationContentType(Annotated am, JavaType baseType) {
904 return null;
905 }
906
907
912
913 @Override
914 public String[] findSerializationPropertyOrder(AnnotatedClass ac) {
915 JsonPropertyOrder order = _findAnnotation(ac, JsonPropertyOrder.class);
916 return (order == null) ? null : order.value();
917 }
918
919 @Override
920 public Boolean findSerializationSortAlphabetically(Annotated ann) {
921 return _findSortAlpha(ann);
922 }
923
924 private final Boolean _findSortAlpha(Annotated ann) {
925 JsonPropertyOrder order = _findAnnotation(ann, JsonPropertyOrder.class);
926
927
928 if ((order != null) && order.alphabetic()) {
929 return Boolean.TRUE;
930 }
931 return null;
932 }
933
934 @Override
935 public void findAndAddVirtualProperties(MapperConfig<?> config, AnnotatedClass ac,
936 List<BeanPropertyWriter> properties) {
937 JsonAppend ann = _findAnnotation(ac, JsonAppend.class);
938 if (ann == null) {
939 return;
940 }
941 final boolean prepend = ann.prepend();
942 JavaType propType = null;
943
944
945 JsonAppend.Attr[] attrs = ann.attrs();
946 for (int i = 0, len = attrs.length; i < len; ++i) {
947 if (propType == null) {
948 propType = config.constructType(Object.class);
949 }
950 BeanPropertyWriter bpw = _constructVirtualProperty(attrs[i],
951 config, ac, propType);
952 if (prepend) {
953 properties.add(i, bpw);
954 } else {
955 properties.add(bpw);
956 }
957 }
958
959
960 JsonAppend.Prop[] props = ann.props();
961 for (int i = 0, len = props.length; i < len; ++i) {
962 BeanPropertyWriter bpw = _constructVirtualProperty(props[i],
963 config, ac);
964 if (prepend) {
965 properties.add(i, bpw);
966 } else {
967 properties.add(bpw);
968 }
969 }
970 }
971
972 protected BeanPropertyWriter _constructVirtualProperty(JsonAppend.Attr attr,
973 MapperConfig<?> config, AnnotatedClass ac, JavaType type)
974 {
975 PropertyMetadata metadata = attr.required() ?
976 PropertyMetadata.STD_REQUIRED : PropertyMetadata.STD_OPTIONAL;
977
978 String attrName = attr.value();
979
980
981 PropertyName propName = _propertyName(attr.propName(), attr.propNamespace());
982 if (!propName.hasSimpleName()) {
983 propName = PropertyName.construct(attrName);
984 }
985
986 AnnotatedMember member = new VirtualAnnotatedMember(ac, ac.getRawType(),
987 attrName, type);
988
989 SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(config,
990 member, propName, metadata, attr.include());
991
992 return AttributePropertyWriter.construct(attrName, propDef,
993 ac.getAnnotations(), type);
994 }
995
996 protected BeanPropertyWriter _constructVirtualProperty(JsonAppend.Prop prop,
997 MapperConfig<?> config, AnnotatedClass ac)
998 {
999 PropertyMetadata metadata = prop.required() ?
1000 PropertyMetadata.STD_REQUIRED : PropertyMetadata.STD_OPTIONAL;
1001 PropertyName propName = _propertyName(prop.name(), prop.namespace());
1002 JavaType type = config.constructType(prop.type());
1003
1004 AnnotatedMember member = new VirtualAnnotatedMember(ac, ac.getRawType(),
1005 propName.getSimpleName(), type);
1006
1007 SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(config,
1008 member, propName, metadata, prop.include());
1009
1010 Class<?> implClass = prop.value();
1011
1012 HandlerInstantiator hi = config.getHandlerInstantiator();
1013 VirtualBeanPropertyWriter bpw = (hi == null) ? null
1014 : hi.virtualPropertyWriterInstance(config, implClass);
1015 if (bpw == null) {
1016 bpw = (VirtualBeanPropertyWriter) ClassUtil.createInstance(implClass,
1017 config.canOverrideAccessModifiers());
1018 }
1019
1020
1021 return bpw.withConfig(config, ac, propDef, type);
1022 }
1023
1024
1029
1030 @Override
1031 public PropertyName findNameForSerialization(Annotated a)
1032 {
1033 boolean useDefault = false;
1034 JsonGetter jg = _findAnnotation(a, JsonGetter.class);
1035 if (jg != null) {
1036 String s = jg.value();
1037
1038 if (!s.isEmpty()) {
1039 return PropertyName.construct(s);
1040 }
1041 useDefault = true;
1042 }
1043 JsonProperty pann = _findAnnotation(a, JsonProperty.class);
1044 if (pann != null) {
1045 return PropertyName.construct(pann.value());
1046 }
1047 if (useDefault || _hasOneOf(a, ANNOTATIONS_TO_INFER_SER)) {
1048 return PropertyName.USE_DEFAULT;
1049 }
1050 return null;
1051 }
1052
1053 @Override
1054 public Boolean hasAsValue(Annotated a) {
1055 JsonValue ann = _findAnnotation(a, JsonValue.class);
1056 if (ann == null) {
1057 return null;
1058 }
1059 return ann.value();
1060 }
1061
1062 @Override
1063 public Boolean hasAnyGetter(Annotated a) {
1064 JsonAnyGetter ann = _findAnnotation(a, JsonAnyGetter.class);
1065 if (ann == null) {
1066 return null;
1067 }
1068 return ann.enabled();
1069 }
1070
1071 @Override
1072 @Deprecated
1073 public boolean hasAnyGetterAnnotation(AnnotatedMethod am) {
1074
1075 return _hasAnnotation(am, JsonAnyGetter.class);
1076 }
1077
1078 @Override
1079 @Deprecated
1080 public boolean hasAsValueAnnotation(AnnotatedMethod am) {
1081 JsonValue ann = _findAnnotation(am, JsonValue.class);
1082
1083 return (ann != null) && ann.value();
1084 }
1085
1086
1091
1092 @Override
1093 public Object findDeserializer(Annotated a)
1094 {
1095 JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
1096 if (ann != null) {
1097 @SuppressWarnings("rawtypes")
1098 Class<? extends JsonDeserializer> deserClass = ann.using();
1099 if (deserClass != JsonDeserializer.None.class) {
1100 return deserClass;
1101 }
1102 }
1103 return null;
1104 }
1105
1106 @Override
1107 public Object findKeyDeserializer(Annotated a)
1108 {
1109 JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
1110 if (ann != null) {
1111 Class<? extends KeyDeserializer> deserClass = ann.keyUsing();
1112 if (deserClass != KeyDeserializer.None.class) {
1113 return deserClass;
1114 }
1115 }
1116 return null;
1117 }
1118
1119 @Override
1120 public Object findContentDeserializer(Annotated a)
1121 {
1122 JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
1123 if (ann != null) {
1124 @SuppressWarnings("rawtypes")
1125 Class<? extends JsonDeserializer> deserClass = ann.contentUsing();
1126 if (deserClass != JsonDeserializer.None.class) {
1127 return deserClass;
1128 }
1129 }
1130 return null;
1131 }
1132
1133 @Override
1134 public Object findDeserializationConverter(Annotated a)
1135 {
1136 JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
1137 return (ann == null) ? null : _classIfExplicit(ann.converter(), Converter.None.class);
1138 }
1139
1140 @Override
1141 public Object findDeserializationContentConverter(AnnotatedMember a)
1142 {
1143 JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class);
1144 return (ann == null) ? null : _classIfExplicit(ann.contentConverter(), Converter.None.class);
1145 }
1146
1147
1152
1153 @Override
1154 public JavaType refineDeserializationType(final MapperConfig<?> config,
1155 final Annotated a, final JavaType baseType) throws JsonMappingException
1156 {
1157 JavaType type = baseType;
1158 final TypeFactory tf = config.getTypeFactory();
1159
1160 final JsonDeserialize jsonDeser = _findAnnotation(a, JsonDeserialize.class);
1161
1162
1163 final Class<?> valueClass = (jsonDeser == null) ? null : _classIfExplicit(jsonDeser.as());
1164 if ((valueClass != null) && !type.hasRawClass(valueClass)
1165 && !_primitiveAndWrapper(type, valueClass)) {
1166 try {
1167 type = tf.constructSpecializedType(type, valueClass);
1168 } catch (IllegalArgumentException iae) {
1169 throw new JsonMappingException(null,
1170 String.format("Failed to narrow type %s with annotation (value %s), from '%s': %s",
1171 type, valueClass.getName(), a.getName(), iae.getMessage()),
1172 iae);
1173 }
1174 }
1175
1176
1177
1178 if (type.isMapLikeType()) {
1179 JavaType keyType = type.getKeyType();
1180 final Class<?> keyClass = (jsonDeser == null) ? null : _classIfExplicit(jsonDeser.keyAs());
1181 if ((keyClass != null)
1182 && !_primitiveAndWrapper(keyType, keyClass)) {
1183 try {
1184 keyType = tf.constructSpecializedType(keyType, keyClass);
1185 type = ((MapLikeType) type).withKeyType(keyType);
1186 } catch (IllegalArgumentException iae) {
1187 throw new JsonMappingException(null,
1188 String.format("Failed to narrow key type of %s with concrete-type annotation (value %s), from '%s': %s",
1189 type, keyClass.getName(), a.getName(), iae.getMessage()),
1190 iae);
1191 }
1192 }
1193 }
1194 JavaType contentType = type.getContentType();
1195 if (contentType != null) {
1196
1197 final Class<?> contentClass = (jsonDeser == null) ? null : _classIfExplicit(jsonDeser.contentAs());
1198 if ((contentClass != null)
1199 && !_primitiveAndWrapper(contentType, contentClass)) {
1200 try {
1201 contentType = tf.constructSpecializedType(contentType, contentClass);
1202 type = type.withContentType(contentType);
1203 } catch (IllegalArgumentException iae) {
1204 throw new JsonMappingException(null,
1205 String.format("Failed to narrow value type of %s with concrete-type annotation (value %s), from '%s': %s",
1206 type, contentClass.getName(), a.getName(), iae.getMessage()),
1207 iae);
1208 }
1209 }
1210 }
1211 return type;
1212 }
1213
1214 @Override
1215 @Deprecated
1216 public Class<?> findDeserializationContentType(Annotated am, JavaType baseContentType) {
1217 return null;
1218 }
1219
1220 @Override
1221 @Deprecated
1222 public Class<?> findDeserializationType(Annotated am, JavaType baseType) {
1223 return null;
1224 }
1225
1226 @Override
1227 @Deprecated
1228 public Class<?> findDeserializationKeyType(Annotated am, JavaType baseKeyType) {
1229 return null;
1230 }
1231
1232
1237
1238 @Override
1239 public Object findValueInstantiator(AnnotatedClass ac)
1240 {
1241 JsonValueInstantiator ann = _findAnnotation(ac, JsonValueInstantiator.class);
1242
1243 return (ann == null) ? null : ann.value();
1244 }
1245
1246 @Override
1247 public Class<?> findPOJOBuilder(AnnotatedClass ac)
1248 {
1249 JsonDeserialize ann = _findAnnotation(ac, JsonDeserialize.class);
1250 return (ann == null) ? null : _classIfExplicit(ann.builder());
1251 }
1252
1253 @Override
1254 public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac)
1255 {
1256 JsonPOJOBuilder ann = _findAnnotation(ac, JsonPOJOBuilder.class);
1257 return (ann == null) ? null : new JsonPOJOBuilder.Value(ann);
1258 }
1259
1260
1265
1266 @Override
1267 public PropertyName findNameForDeserialization(Annotated a)
1268 {
1269
1270
1271 boolean useDefault = false;
1272 JsonSetter js = _findAnnotation(a, JsonSetter.class);
1273 if (js != null) {
1274 String s = js.value();
1275
1276 if (s.isEmpty()) {
1277 useDefault = true;
1278 } else {
1279 return PropertyName.construct(s);
1280 }
1281 }
1282 JsonProperty pann = _findAnnotation(a, JsonProperty.class);
1283 if (pann != null) {
1284 return PropertyName.construct(pann.value());
1285 }
1286 if (useDefault || _hasOneOf(a, ANNOTATIONS_TO_INFER_DESER)) {
1287 return PropertyName.USE_DEFAULT;
1288 }
1289 return null;
1290 }
1291
1292 @Override
1293 public Boolean hasAnySetter(Annotated a) {
1294 JsonAnySetter ann = _findAnnotation(a, JsonAnySetter.class);
1295 return (ann == null) ? null : ann.enabled();
1296 }
1297
1298 @Override
1299 public JsonSetter.Value findSetterInfo(Annotated a) {
1300 return JsonSetter.Value.from(_findAnnotation(a, JsonSetter.class));
1301 }
1302
1303 @Override
1304 public Boolean findMergeInfo(Annotated a) {
1305 JsonMerge ann = _findAnnotation(a, JsonMerge.class);
1306 return (ann == null) ? null : ann.value().asBoolean();
1307 }
1308
1309 @Override
1310 @Deprecated
1311 public boolean hasAnySetterAnnotation(AnnotatedMethod am) {
1312 return _hasAnnotation(am, JsonAnySetter.class);
1313 }
1314
1315 @Override
1316 @Deprecated
1317 public boolean hasCreatorAnnotation(Annotated a)
1318 {
1319
1322 JsonCreator ann = _findAnnotation(a, JsonCreator.class);
1323 if (ann != null) {
1324 return (ann.mode() != JsonCreator.Mode.DISABLED);
1325 }
1326
1327
1328 if (_cfgConstructorPropertiesImpliesCreator ) {
1329 if (a instanceof AnnotatedConstructor) {
1330 if (_java7Helper != null) {
1331 Boolean b = _java7Helper.hasCreatorAnnotation(a);
1332 if (b != null) {
1333 return b.booleanValue();
1334 }
1335 }
1336 }
1337 }
1338 return false;
1339 }
1340
1341 @Override
1342 @Deprecated
1343 public JsonCreator.Mode findCreatorBinding(Annotated a) {
1344 JsonCreator ann = _findAnnotation(a, JsonCreator.class);
1345 return (ann == null) ? null : ann.mode();
1346 }
1347
1348 @Override
1349 public JsonCreator.Mode findCreatorAnnotation(MapperConfig<?> config, Annotated a) {
1350 JsonCreator ann = _findAnnotation(a, JsonCreator.class);
1351 if (ann != null) {
1352 return ann.mode();
1353 }
1354 if (_cfgConstructorPropertiesImpliesCreator
1355 && config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)
1356 ) {
1357 if (a instanceof AnnotatedConstructor) {
1358 if (_java7Helper != null) {
1359 Boolean b = _java7Helper.hasCreatorAnnotation(a);
1360 if ((b != null) && b.booleanValue()) {
1361
1362
1363 return JsonCreator.Mode.PROPERTIES;
1364 }
1365 }
1366 }
1367 }
1368 return null;
1369 }
1370
1371
1376
1377 protected boolean _isIgnorable(Annotated a)
1378 {
1379 JsonIgnore ann = _findAnnotation(a, JsonIgnore.class);
1380 if (ann != null) {
1381 return ann.value();
1382 }
1383 if (_java7Helper != null) {
1384 Boolean b = _java7Helper.findTransient(a);
1385 if (b != null) {
1386 return b.booleanValue();
1387 }
1388 }
1389 return false;
1390 }
1391
1392 protected Class<?> _classIfExplicit(Class<?> cls) {
1393 if (cls == null || ClassUtil.isBogusClass(cls)) {
1394 return null;
1395 }
1396 return cls;
1397 }
1398
1399 protected Class<?> _classIfExplicit(Class<?> cls, Class<?> implicit) {
1400 cls = _classIfExplicit(cls);
1401 return (cls == null || cls == implicit) ? null : cls;
1402 }
1403
1404 protected PropertyName _propertyName(String localName, String namespace) {
1405 if (localName.isEmpty()) {
1406 return PropertyName.USE_DEFAULT;
1407 }
1408 if (namespace == null || namespace.isEmpty()) {
1409 return PropertyName.construct(localName);
1410 }
1411 return PropertyName.construct(localName, namespace);
1412 }
1413
1414 protected PropertyName _findConstructorName(Annotated a)
1415 {
1416 if (a instanceof AnnotatedParameter) {
1417 AnnotatedParameter p = (AnnotatedParameter) a;
1418 AnnotatedWithParams ctor = p.getOwner();
1419
1420 if (ctor != null) {
1421 if (_java7Helper != null) {
1422 PropertyName name = _java7Helper.findConstructorName(p);
1423 if (name != null) {
1424 return name;
1425 }
1426 }
1427 }
1428 }
1429 return null;
1430 }
1431
1432
1436 @SuppressWarnings("deprecation")
1437 protected TypeResolverBuilder<?> _findTypeResolver(MapperConfig<?> config,
1438 Annotated ann, JavaType baseType)
1439 {
1440
1441 TypeResolverBuilder<?> b;
1442 JsonTypeInfo info = _findAnnotation(ann, JsonTypeInfo.class);
1443 JsonTypeResolver resAnn = _findAnnotation(ann, JsonTypeResolver.class);
1444
1445 if (resAnn != null) {
1446 if (info == null) {
1447 return null;
1448 }
1449
1450
1451 b = config.typeResolverBuilderInstance(ann, resAnn.value());
1452 } else {
1453 if (info == null) {
1454 return null;
1455 }
1456
1457 if (info.use() == JsonTypeInfo.Id.NONE) {
1458 return _constructNoTypeResolverBuilder();
1459 }
1460 b = _constructStdTypeResolverBuilder();
1461 }
1462
1463 JsonTypeIdResolver idResInfo = _findAnnotation(ann, JsonTypeIdResolver.class);
1464 TypeIdResolver idRes = (idResInfo == null) ? null
1465 : config.typeIdResolverInstance(ann, idResInfo.value());
1466 if (idRes != null) {
1467 idRes.init(baseType);
1468 }
1469 b = b.init(info.use(), idRes);
1470
1471
1472
1473 JsonTypeInfo.As inclusion = info.include();
1474 if (inclusion == JsonTypeInfo.As.EXTERNAL_PROPERTY && (ann instanceof AnnotatedClass)) {
1475 inclusion = JsonTypeInfo.As.PROPERTY;
1476 }
1477 b = b.inclusion(inclusion);
1478 b = b.typeProperty(info.property());
1479 Class<?> defaultImpl = info.defaultImpl();
1480
1481
1482
1483
1484
1485 if (defaultImpl != JsonTypeInfo.None.class && !defaultImpl.isAnnotation()) {
1486 b = b.defaultImpl(defaultImpl);
1487 }
1488 b = b.typeIdVisibility(info.visible());
1489 return b;
1490 }
1491
1492
1496 protected StdTypeResolverBuilder _constructStdTypeResolverBuilder() {
1497 return new StdTypeResolverBuilder();
1498 }
1499
1500
1504 protected StdTypeResolverBuilder _constructNoTypeResolverBuilder() {
1505 return StdTypeResolverBuilder.noTypeInfoBuilder();
1506 }
1507
1508 private boolean _primitiveAndWrapper(Class<?> baseType, Class<?> refinement)
1509 {
1510 if (baseType.isPrimitive()) {
1511 return baseType == ClassUtil.primitiveType(refinement);
1512 }
1513 if (refinement.isPrimitive()) {
1514 return refinement == ClassUtil.primitiveType(baseType);
1515 }
1516 return false;
1517 }
1518
1519 private boolean _primitiveAndWrapper(JavaType baseType, Class<?> refinement)
1520 {
1521 if (baseType.isPrimitive()) {
1522 return baseType.hasRawClass(ClassUtil.primitiveType(refinement));
1523 }
1524 if (refinement.isPrimitive()) {
1525 return refinement == ClassUtil.primitiveType(baseType.getRawClass());
1526 }
1527 return false;
1528 }
1529 }
1530