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 /** 27 * {@link AnnotationIntrospector} implementation that handles standard 28 * Jackson annotations. 29 */ 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 // since 2.9 60 }; 61 62 // NOTE: loading of Java7 dependencies is encapsulated by handlers in Java7Support, 63 // here we do not really need any handling; but for extra-safety use try-catch 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 /** 74 * Since introspection of annotation types is a performance issue in some 75 * use cases (rare, but do exist), let's try a simple cache to reduce 76 * need for actual meta-annotation introspection. 77 *<p> 78 * Non-final only because it needs to be re-created after deserialization. 79 * 80 * @since 2.7 81 */ 82 protected transient LRUMap<Class<?>,Boolean> _annotationsInside = new LRUMap<Class<?>,Boolean>(48, 48); 83 84 /* 85 /********************************************************** 86 /* Local configuration settings 87 /********************************************************** 88 */ 89 90 /** 91 * See {@link #setConstructorPropertiesImpliesCreator(boolean)} for 92 * explanation. 93 *<p> 94 * Defaults to true. 95 * 96 * @since 2.7.4 97 */ 98 protected boolean _cfgConstructorPropertiesImpliesCreator = true; 99 100 /* 101 /********************************************************** 102 /* Life-cycle 103 /********************************************************** 104 */ 105 JacksonAnnotationIntrospector()106 public JacksonAnnotationIntrospector() { } 107 108 @Override version()109 public Version version() { 110 return com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION; 111 } 112 readResolve()113 protected Object readResolve() { 114 if (_annotationsInside == null) { 115 _annotationsInside = new LRUMap<Class<?>,Boolean>(48, 48); 116 } 117 return this; 118 } 119 120 /* 121 /********************************************************** 122 /* Configuration 123 /********************************************************** 124 */ 125 126 /** 127 * Method for changing behavior of {@link java.beans.ConstructorProperties}: 128 * if set to `true`, existence DOES indicate that the given constructor should 129 * be considered a creator; `false` that it should NOT be considered a creator 130 * without explicit use of <code>JsonCreator</code> annotation. 131 *<p> 132 * Default setting is `true` 133 * 134 * @since 2.7.4 135 */ setConstructorPropertiesImpliesCreator(boolean b)136 public JacksonAnnotationIntrospector setConstructorPropertiesImpliesCreator(boolean b) 137 { 138 _cfgConstructorPropertiesImpliesCreator = b; 139 return this; 140 } 141 142 /* 143 /********************************************************** 144 /* General annotation properties 145 /********************************************************** 146 */ 147 148 /** 149 * Annotations with meta-annotation {@link JacksonAnnotationsInside} 150 * are considered bundles. 151 */ 152 @Override isAnnotationBundle(Annotation ann)153 public boolean isAnnotationBundle(Annotation ann) { 154 // 22-Sep-2015, tatu: Caching here has modest effect on JavaSE, and only 155 // mostly in degenerate cases where introspection used more often than 156 // it should (like recreating ObjectMapper once per read/write). 157 // But it may be more beneficial on platforms like Android (should verify) 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 /* 168 /********************************************************** 169 /* General annotations 170 /********************************************************** 171 */ 172 173 /** 174 * Since 2.6, we have supported use of {@link JsonProperty} for specifying 175 * explicit serialized name 176 */ 177 @Override 178 @Deprecated // since 2.8 findEnumValue(Enum<?> value)179 public String findEnumValue(Enum<?> value) 180 { 181 // 11-Jun-2015, tatu: As per [databind#677], need to allow explicit naming. 182 // Unfortunately cannot quite use standard AnnotatedClass here (due to various 183 // reasons, including odd representation JVM uses); has to do for now 184 try { 185 // We know that values are actually static fields with matching name so: 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 // 17-Sep-2015, tatu: Anything we could/should do here? 198 } catch (NoSuchFieldException e) { 199 // 17-Sep-2015, tatu: should not really happen. But... can we do anything? 200 } 201 return value.name(); 202 } 203 204 @Override // since 2.7 findEnumValues(Class<?> enumType, Enum<?>[] enumValues, String[] names)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 // and then stitch them together if and as necessary 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 // since 2.11 findEnumAliases(Class<?> enumType, Enum<?>[] enumValues, String[][] aliasList)238 public void findEnumAliases(Class<?> enumType, Enum<?>[] enumValues, String[][] aliasList) 239 { 240 // Main complication: discrepancy between Field that represent enum value, 241 // Enum abstraction; joint by name but not reference 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 // Find matching enum (could create Ma 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 /** 262 * Finds the Enum value that should be considered the default value, if possible. 263 * <p> 264 * This implementation relies on {@link JsonEnumDefaultValue} annotation to determine the default value if present. 265 * 266 * @param enumCls The Enum class to scan for the default value. 267 * @return null if none found or it's not possible to determine one. 268 * @since 2.8 269 */ 270 @Override findDefaultEnumValue(Class<Enum<?>> enumCls)271 public Enum<?> findDefaultEnumValue(Class<Enum<?>> enumCls) { 272 return ClassUtil.findFirstAnnotatedEnumValue(enumCls, JsonEnumDefaultValue.class); 273 } 274 275 /* 276 /********************************************************** 277 /* General class annotations 278 /********************************************************** 279 */ 280 281 @Override findRootName(AnnotatedClass ac)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 isIgnorableType(AnnotatedClass ac)296 public Boolean isIgnorableType(AnnotatedClass ac) { 297 JsonIgnoreType ignore = _findAnnotation(ac, JsonIgnoreType.class); 298 return (ignore == null) ? null : ignore.value(); 299 } 300 301 @Override // since 2.12 findPropertyIgnoralByName(MapperConfig<?> config, Annotated a)302 public JsonIgnoreProperties.Value findPropertyIgnoralByName(MapperConfig<?> config, Annotated a) 303 { 304 JsonIgnoreProperties v = _findAnnotation(a, JsonIgnoreProperties.class); 305 if (v == null) { 306 return JsonIgnoreProperties.Value.empty(); 307 } 308 return JsonIgnoreProperties.Value.from(v); 309 } 310 311 // Keep around until 3.x 312 @Deprecated // since 2.12 313 @Override findPropertyIgnorals(Annotated ac)314 public JsonIgnoreProperties.Value findPropertyIgnorals(Annotated ac) { 315 return findPropertyIgnoralByName(null, ac); 316 } 317 318 @Override findPropertyInclusionByName(MapperConfig<?> config, Annotated a)319 public JsonIncludeProperties.Value findPropertyInclusionByName(MapperConfig<?> config, Annotated a) 320 { 321 JsonIncludeProperties v = _findAnnotation(a, JsonIncludeProperties.class); 322 if (v == null) { 323 return JsonIncludeProperties.Value.all(); 324 } 325 return JsonIncludeProperties.Value.from(v); 326 } 327 328 @Override findFilterId(Annotated a)329 public Object findFilterId(Annotated a) { 330 JsonFilter ann = _findAnnotation(a, JsonFilter.class); 331 if (ann != null) { 332 String id = ann.value(); 333 // Empty String is same as not having annotation, to allow overrides 334 if (id.length() > 0) { 335 return id; 336 } 337 } 338 return null; 339 } 340 341 @Override findNamingStrategy(AnnotatedClass ac)342 public Object findNamingStrategy(AnnotatedClass ac) 343 { 344 JsonNaming ann = _findAnnotation(ac, JsonNaming.class); 345 return (ann == null) ? null : ann.value(); 346 } 347 348 @Override findClassDescription(AnnotatedClass ac)349 public String findClassDescription(AnnotatedClass ac) { 350 JsonClassDescription ann = _findAnnotation(ac, JsonClassDescription.class); 351 return (ann == null) ? null : ann.value(); 352 } 353 354 /* 355 /********************************************************** 356 /* Property auto-detection 357 /********************************************************** 358 */ 359 360 @Override findAutoDetectVisibility(AnnotatedClass ac, VisibilityChecker<?> checker)361 public VisibilityChecker<?> findAutoDetectVisibility(AnnotatedClass ac, 362 VisibilityChecker<?> checker) 363 { 364 JsonAutoDetect ann = _findAnnotation(ac, JsonAutoDetect.class); 365 return (ann == null) ? checker : checker.with(ann); 366 } 367 368 /* 369 /********************************************************** 370 /* General member (field, method/constructor) annotations 371 /********************************************************** 372 */ 373 374 @Override findImplicitPropertyName(AnnotatedMember m)375 public String findImplicitPropertyName(AnnotatedMember m) { 376 PropertyName n = _findConstructorName(m); 377 return (n == null) ? null : n.getSimpleName(); 378 } 379 380 @Override findPropertyAliases(Annotated m)381 public List<PropertyName> findPropertyAliases(Annotated m) { 382 JsonAlias ann = _findAnnotation(m, JsonAlias.class); 383 if (ann == null) { 384 return null; 385 } 386 String[] strs = ann.value(); 387 final int len = strs.length; 388 if (len == 0) { 389 return Collections.emptyList(); 390 } 391 List<PropertyName> result = new ArrayList<>(len); 392 for (int i = 0; i < len; ++i) { 393 result.add(PropertyName.construct(strs[i])); 394 } 395 return result; 396 } 397 398 @Override hasIgnoreMarker(AnnotatedMember m)399 public boolean hasIgnoreMarker(AnnotatedMember m) { 400 return _isIgnorable(m); 401 } 402 403 @Override hasRequiredMarker(AnnotatedMember m)404 public Boolean hasRequiredMarker(AnnotatedMember m) 405 { 406 JsonProperty ann = _findAnnotation(m, JsonProperty.class); 407 if (ann != null) { 408 return ann.required(); 409 } 410 return null; 411 } 412 413 @Override findPropertyAccess(Annotated m)414 public JsonProperty.Access findPropertyAccess(Annotated m) { 415 JsonProperty ann = _findAnnotation(m, JsonProperty.class); 416 if (ann != null) { 417 return ann.access(); 418 } 419 return null; 420 } 421 422 @Override findPropertyDescription(Annotated ann)423 public String findPropertyDescription(Annotated ann) { 424 JsonPropertyDescription desc = _findAnnotation(ann, JsonPropertyDescription.class); 425 return (desc == null) ? null : desc.value(); 426 } 427 428 @Override findPropertyIndex(Annotated ann)429 public Integer findPropertyIndex(Annotated ann) { 430 JsonProperty prop = _findAnnotation(ann, JsonProperty.class); 431 if (prop != null) { 432 int ix = prop.index(); 433 if (ix != JsonProperty.INDEX_UNKNOWN) { 434 return Integer.valueOf(ix); 435 } 436 } 437 return null; 438 } 439 440 @Override findPropertyDefaultValue(Annotated ann)441 public String findPropertyDefaultValue(Annotated ann) { 442 JsonProperty prop = _findAnnotation(ann, JsonProperty.class); 443 if (prop == null) { 444 return null; 445 } 446 String str = prop.defaultValue(); 447 // Since annotations do not allow nulls, need to assume empty means "none" 448 return str.isEmpty() ? null : str; 449 } 450 451 @Override findFormat(Annotated ann)452 public JsonFormat.Value findFormat(Annotated ann) { 453 JsonFormat f = _findAnnotation(ann, JsonFormat.class); 454 // NOTE: could also just call `JsonFormat.Value.from()` with `null` 455 // too, but that returns "empty" instance 456 return (f == null) ? null : JsonFormat.Value.from(f); 457 } 458 459 @Override findReferenceType(AnnotatedMember member)460 public ReferenceProperty findReferenceType(AnnotatedMember member) 461 { 462 JsonManagedReference ref1 = _findAnnotation(member, JsonManagedReference.class); 463 if (ref1 != null) { 464 return AnnotationIntrospector.ReferenceProperty.managed(ref1.value()); 465 } 466 JsonBackReference ref2 = _findAnnotation(member, JsonBackReference.class); 467 if (ref2 != null) { 468 return AnnotationIntrospector.ReferenceProperty.back(ref2.value()); 469 } 470 return null; 471 } 472 473 @Override findUnwrappingNameTransformer(AnnotatedMember member)474 public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member) 475 { 476 JsonUnwrapped ann = _findAnnotation(member, JsonUnwrapped.class); 477 // if not enabled, just means annotation is not enabled; not necessarily 478 // that unwrapping should not be done (relevant when using chained introspectors) 479 if (ann == null || !ann.enabled()) { 480 return null; 481 } 482 String prefix = ann.prefix(); 483 String suffix = ann.suffix(); 484 return NameTransformer.simpleTransformer(prefix, suffix); 485 } 486 487 @Override // since 2.9 findInjectableValue(AnnotatedMember m)488 public JacksonInject.Value findInjectableValue(AnnotatedMember m) { 489 JacksonInject ann = _findAnnotation(m, JacksonInject.class); 490 if (ann == null) { 491 return null; 492 } 493 // Empty String means that we should use name of declared value class. 494 JacksonInject.Value v = JacksonInject.Value.from(ann); 495 if (!v.hasId()) { 496 Object id; 497 // slight complication; for setters, type 498 if (!(m instanceof AnnotatedMethod)) { 499 id = m.getRawType().getName(); 500 } else { 501 AnnotatedMethod am = (AnnotatedMethod) m; 502 if (am.getParameterCount() == 0) { // getter 503 id = m.getRawType().getName(); 504 } else { // setter 505 id = am.getRawParameterType(0).getName(); 506 } 507 } 508 v = v.withId(id); 509 } 510 return v; 511 } 512 513 @Override 514 @Deprecated // since 2.9 findInjectableValueId(AnnotatedMember m)515 public Object findInjectableValueId(AnnotatedMember m) { 516 JacksonInject.Value v = findInjectableValue(m); 517 return (v == null) ? null : v.getId(); 518 } 519 520 @Override findViews(Annotated a)521 public Class<?>[] findViews(Annotated a) 522 { 523 JsonView ann = _findAnnotation(a, JsonView.class); 524 return (ann == null) ? null : ann.value(); 525 } 526 527 @Override // since 2.7 resolveSetterConflict(MapperConfig<?> config, AnnotatedMethod setter1, AnnotatedMethod setter2)528 public AnnotatedMethod resolveSetterConflict(MapperConfig<?> config, 529 AnnotatedMethod setter1, AnnotatedMethod setter2) 530 { 531 Class<?> cls1 = setter1.getRawParameterType(0); 532 Class<?> cls2 = setter2.getRawParameterType(0); 533 534 // First: prefer primitives over non-primitives 535 // 11-Dec-2015, tatu: TODO, perhaps consider wrappers for primitives too? 536 if (cls1.isPrimitive()) { 537 if (!cls2.isPrimitive()) { 538 return setter1; 539 } 540 } else if (cls2.isPrimitive()) { 541 return setter2; 542 } 543 544 if (cls1 == String.class) { 545 if (cls2 != String.class) { 546 return setter1; 547 } 548 } else if (cls2 == String.class) { 549 return setter2; 550 } 551 552 return null; 553 } 554 555 @Override // since 2.11 findRenameByField(MapperConfig<?> config, AnnotatedField f, PropertyName implName)556 public PropertyName findRenameByField(MapperConfig<?> config, 557 AnnotatedField f, PropertyName implName) { 558 // Nothing to report, only used by modules. But define just as documentation 559 return null; 560 } 561 562 /* 563 /********************************************************** 564 /* Annotations for Polymorphic Type handling 565 /********************************************************** 566 */ 567 568 @Override findTypeResolver(MapperConfig<?> config, AnnotatedClass ac, JavaType baseType)569 public TypeResolverBuilder<?> findTypeResolver(MapperConfig<?> config, 570 AnnotatedClass ac, JavaType baseType) 571 { 572 return _findTypeResolver(config, ac, baseType); 573 } 574 575 @Override findPropertyTypeResolver(MapperConfig<?> config, AnnotatedMember am, JavaType baseType)576 public TypeResolverBuilder<?> findPropertyTypeResolver(MapperConfig<?> config, 577 AnnotatedMember am, JavaType baseType) 578 { 579 /* As per definition of @JsonTypeInfo, should only apply to contents of container 580 * (collection, map) types, not container types themselves: 581 */ 582 // 17-Apr-2016, tatu: For 2.7.4 make sure ReferenceType also included 583 if (baseType.isContainerType() || baseType.isReferenceType()) { 584 return null; 585 } 586 // No per-member type overrides (yet) 587 return _findTypeResolver(config, am, baseType); 588 } 589 590 @Override findPropertyContentTypeResolver(MapperConfig<?> config, AnnotatedMember am, JavaType containerType)591 public TypeResolverBuilder<?> findPropertyContentTypeResolver(MapperConfig<?> config, 592 AnnotatedMember am, JavaType containerType) 593 { 594 /* First: let's ensure property is a container type: caller should have 595 * verified but just to be sure 596 */ 597 if (containerType.getContentType() == null) { 598 throw new IllegalArgumentException("Must call method with a container or reference type (got "+containerType+")"); 599 } 600 return _findTypeResolver(config, am, containerType); 601 } 602 603 @Override findSubtypes(Annotated a)604 public List<NamedType> findSubtypes(Annotated a) 605 { 606 JsonSubTypes t = _findAnnotation(a, JsonSubTypes.class); 607 if (t == null) return null; 608 JsonSubTypes.Type[] types = t.value(); 609 ArrayList<NamedType> result = new ArrayList<NamedType>(types.length); 610 for (JsonSubTypes.Type type : types) { 611 result.add(new NamedType(type.value(), type.name())); 612 // [databind#2761]: alternative set of names to use 613 for (String name : type.names()) { 614 result.add(new NamedType(type.value(), name)); 615 } 616 } 617 return result; 618 } 619 620 @Override findTypeName(AnnotatedClass ac)621 public String findTypeName(AnnotatedClass ac) 622 { 623 JsonTypeName tn = _findAnnotation(ac, JsonTypeName.class); 624 return (tn == null) ? null : tn.value(); 625 } 626 627 @Override isTypeId(AnnotatedMember member)628 public Boolean isTypeId(AnnotatedMember member) { 629 return _hasAnnotation(member, JsonTypeId.class); 630 } 631 632 /* 633 /********************************************************** 634 /* Annotations for Object Id handling 635 /********************************************************** 636 */ 637 638 @Override findObjectIdInfo(Annotated ann)639 public ObjectIdInfo findObjectIdInfo(Annotated ann) { 640 JsonIdentityInfo info = _findAnnotation(ann, JsonIdentityInfo.class); 641 if (info == null || info.generator() == ObjectIdGenerators.None.class) { 642 return null; 643 } 644 // In future may need to allow passing namespace? 645 PropertyName name = PropertyName.construct(info.property()); 646 return new ObjectIdInfo(name, info.scope(), info.generator(), info.resolver()); 647 } 648 649 @Override findObjectReferenceInfo(Annotated ann, ObjectIdInfo objectIdInfo)650 public ObjectIdInfo findObjectReferenceInfo(Annotated ann, ObjectIdInfo objectIdInfo) { 651 JsonIdentityReference ref = _findAnnotation(ann, JsonIdentityReference.class); 652 if (ref == null) { 653 return objectIdInfo; 654 } 655 if (objectIdInfo == null) { 656 objectIdInfo = ObjectIdInfo.empty(); 657 } 658 return objectIdInfo.withAlwaysAsId(ref.alwaysAsId()); 659 } 660 661 /* 662 /********************************************************** 663 /* Serialization: general annotations 664 /********************************************************** 665 */ 666 667 @Override findSerializer(Annotated a)668 public Object findSerializer(Annotated a) 669 { 670 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); 671 if (ann != null) { 672 @SuppressWarnings("rawtypes") 673 Class<? extends JsonSerializer> serClass = ann.using(); 674 if (serClass != JsonSerializer.None.class) { 675 return serClass; 676 } 677 } 678 679 /* 18-Oct-2010, tatu: [JACKSON-351] @JsonRawValue handled just here, for now; 680 * if we need to get raw indicator from other sources need to add 681 * separate accessor within {@link AnnotationIntrospector} interface. 682 */ 683 JsonRawValue annRaw = _findAnnotation(a, JsonRawValue.class); 684 if ((annRaw != null) && annRaw.value()) { 685 // let's construct instance with nominal type: 686 Class<?> cls = a.getRawType(); 687 return new RawSerializer<Object>(cls); 688 } 689 return null; 690 } 691 692 @Override findKeySerializer(Annotated a)693 public Object findKeySerializer(Annotated a) 694 { 695 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); 696 if (ann != null) { 697 @SuppressWarnings("rawtypes") 698 Class<? extends JsonSerializer> serClass = ann.keyUsing(); 699 if (serClass != JsonSerializer.None.class) { 700 return serClass; 701 } 702 } 703 return null; 704 } 705 706 @Override findContentSerializer(Annotated a)707 public Object findContentSerializer(Annotated a) 708 { 709 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); 710 if (ann != null) { 711 @SuppressWarnings("rawtypes") 712 Class<? extends JsonSerializer> serClass = ann.contentUsing(); 713 if (serClass != JsonSerializer.None.class) { 714 return serClass; 715 } 716 } 717 return null; 718 } 719 720 @Override findNullSerializer(Annotated a)721 public Object findNullSerializer(Annotated a) 722 { 723 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); 724 if (ann != null) { 725 @SuppressWarnings("rawtypes") 726 Class<? extends JsonSerializer> serClass = ann.nullsUsing(); 727 if (serClass != JsonSerializer.None.class) { 728 return serClass; 729 } 730 } 731 return null; 732 } 733 734 @Override findPropertyInclusion(Annotated a)735 public JsonInclude.Value findPropertyInclusion(Annotated a) 736 { 737 JsonInclude inc = _findAnnotation(a, JsonInclude.class); 738 JsonInclude.Value value = (inc == null) ? JsonInclude.Value.empty() : JsonInclude.Value.from(inc); 739 740 // only consider deprecated variant if we didn't have non-deprecated one: 741 if (value.getValueInclusion() == JsonInclude.Include.USE_DEFAULTS) { 742 value = _refinePropertyInclusion(a, value); 743 } 744 return value; 745 } 746 747 @SuppressWarnings("deprecation") _refinePropertyInclusion(Annotated a, JsonInclude.Value value)748 private JsonInclude.Value _refinePropertyInclusion(Annotated a, JsonInclude.Value value) { 749 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); 750 if (ann != null) { 751 switch (ann.include()) { 752 case ALWAYS: 753 return value.withValueInclusion(JsonInclude.Include.ALWAYS); 754 case NON_NULL: 755 return value.withValueInclusion(JsonInclude.Include.NON_NULL); 756 case NON_DEFAULT: 757 return value.withValueInclusion(JsonInclude.Include.NON_DEFAULT); 758 case NON_EMPTY: 759 return value.withValueInclusion(JsonInclude.Include.NON_EMPTY); 760 case DEFAULT_INCLUSION: 761 default: 762 } 763 } 764 return value; 765 } 766 767 @Override findSerializationTyping(Annotated a)768 public JsonSerialize.Typing findSerializationTyping(Annotated a) 769 { 770 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); 771 return (ann == null) ? null : ann.typing(); 772 } 773 774 @Override findSerializationConverter(Annotated a)775 public Object findSerializationConverter(Annotated a) { 776 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); 777 return (ann == null) ? null : _classIfExplicit(ann.converter(), Converter.None.class); 778 } 779 780 @Override findSerializationContentConverter(AnnotatedMember a)781 public Object findSerializationContentConverter(AnnotatedMember a) { 782 JsonSerialize ann = _findAnnotation(a, JsonSerialize.class); 783 return (ann == null) ? null : _classIfExplicit(ann.contentConverter(), Converter.None.class); 784 } 785 786 /* 787 /********************************************************** 788 /* Serialization: type refinements 789 /********************************************************** 790 */ 791 792 @Override refineSerializationType(final MapperConfig<?> config, final Annotated a, final JavaType baseType)793 public JavaType refineSerializationType(final MapperConfig<?> config, 794 final Annotated a, final JavaType baseType) throws JsonMappingException 795 { 796 JavaType type = baseType; 797 final TypeFactory tf = config.getTypeFactory(); 798 799 final JsonSerialize jsonSer = _findAnnotation(a, JsonSerialize.class); 800 801 // Ok: start by refining the main type itself; common to all types 802 803 final Class<?> serClass = (jsonSer == null) ? null : _classIfExplicit(jsonSer.as()); 804 if (serClass != null) { 805 if (type.hasRawClass(serClass)) { 806 // 30-Nov-2015, tatu: As per [databind#1023], need to allow forcing of 807 // static typing this way 808 type = type.withStaticTyping(); 809 } else { 810 Class<?> currRaw = type.getRawClass(); 811 try { 812 // 11-Oct-2015, tatu: For deser, we call `TypeFactory.constructSpecializedType()`, 813 // may be needed here too in future? 814 if (serClass.isAssignableFrom(currRaw)) { // common case 815 type = tf.constructGeneralizedType(type, serClass); 816 } else if (currRaw.isAssignableFrom(serClass)) { // specialization, ok as well 817 type = tf.constructSpecializedType(type, serClass); 818 } else if (_primitiveAndWrapper(currRaw, serClass)) { 819 // 27-Apr-2017, tatu: [databind#1592] ignore primitive<->wrapper refinements 820 type = type.withStaticTyping(); 821 } else { 822 throw new JsonMappingException(null, 823 String.format("Cannot refine serialization type %s into %s; types not related", 824 type, serClass.getName())); 825 } 826 } catch (IllegalArgumentException iae) { 827 throw new JsonMappingException(null, 828 String.format("Failed to widen type %s with annotation (value %s), from '%s': %s", 829 type, serClass.getName(), a.getName(), iae.getMessage()), 830 iae); 831 } 832 } 833 } 834 // Then further processing for container types 835 836 // First, key type (for Maps, Map-like types): 837 if (type.isMapLikeType()) { 838 JavaType keyType = type.getKeyType(); 839 final Class<?> keyClass = (jsonSer == null) ? null : _classIfExplicit(jsonSer.keyAs()); 840 if (keyClass != null) { 841 if (keyType.hasRawClass(keyClass)) { 842 keyType = keyType.withStaticTyping(); 843 } else { 844 Class<?> currRaw = keyType.getRawClass(); 845 try { 846 // 19-May-2016, tatu: As per [databind#1231], [databind#1178] may need to actually 847 // specialize (narrow) type sometimes, even if more commonly opposite 848 // is needed. 849 if (keyClass.isAssignableFrom(currRaw)) { // common case 850 keyType = tf.constructGeneralizedType(keyType, keyClass); 851 } else if (currRaw.isAssignableFrom(keyClass)) { // specialization, ok as well 852 keyType = tf.constructSpecializedType(keyType, keyClass); 853 } else if (_primitiveAndWrapper(currRaw, keyClass)) { 854 // 27-Apr-2017, tatu: [databind#1592] ignore primitive<->wrapper refinements 855 keyType = keyType.withStaticTyping(); 856 } else { 857 throw new JsonMappingException(null, 858 String.format("Cannot refine serialization key type %s into %s; types not related", 859 keyType, keyClass.getName())); 860 } 861 } catch (IllegalArgumentException iae) { 862 throw new JsonMappingException(null, 863 String.format("Failed to widen key type of %s with concrete-type annotation (value %s), from '%s': %s", 864 type, keyClass.getName(), a.getName(), iae.getMessage()), 865 iae); 866 } 867 } 868 type = ((MapLikeType) type).withKeyType(keyType); 869 } 870 } 871 872 JavaType contentType = type.getContentType(); 873 if (contentType != null) { // collection[like], map[like], array, reference 874 // And then value types for all containers: 875 final Class<?> contentClass = (jsonSer == null) ? null : _classIfExplicit(jsonSer.contentAs()); 876 if (contentClass != null) { 877 if (contentType.hasRawClass(contentClass)) { 878 contentType = contentType.withStaticTyping(); 879 } else { 880 // 03-Apr-2016, tatu: As per [databind#1178], may need to actually 881 // specialize (narrow) type sometimes, even if more commonly opposite 882 // is needed. 883 Class<?> currRaw = contentType.getRawClass(); 884 try { 885 if (contentClass.isAssignableFrom(currRaw)) { // common case 886 contentType = tf.constructGeneralizedType(contentType, contentClass); 887 } else if (currRaw.isAssignableFrom(contentClass)) { // specialization, ok as well 888 contentType = tf.constructSpecializedType(contentType, contentClass); 889 } else if (_primitiveAndWrapper(currRaw, contentClass)) { 890 // 27-Apr-2017, tatu: [databind#1592] ignore primitive<->wrapper refinements 891 contentType = contentType.withStaticTyping(); 892 } else { 893 throw new JsonMappingException(null, 894 String.format("Cannot refine serialization content type %s into %s; types not related", 895 contentType, contentClass.getName())); 896 } 897 } catch (IllegalArgumentException iae) { // shouldn't really happen 898 throw new JsonMappingException(null, 899 String.format("Internal error: failed to refine value type of %s with concrete-type annotation (value %s), from '%s': %s", 900 type, contentClass.getName(), a.getName(), iae.getMessage()), 901 iae); 902 } 903 } 904 type = type.withContentType(contentType); 905 } 906 } 907 return type; 908 } 909 910 @Override 911 @Deprecated // since 2.7 findSerializationType(Annotated am)912 public Class<?> findSerializationType(Annotated am) { 913 return null; 914 } 915 916 @Override 917 @Deprecated // since 2.7 findSerializationKeyType(Annotated am, JavaType baseType)918 public Class<?> findSerializationKeyType(Annotated am, JavaType baseType) { 919 return null; 920 } 921 922 @Override 923 @Deprecated // since 2.7 findSerializationContentType(Annotated am, JavaType baseType)924 public Class<?> findSerializationContentType(Annotated am, JavaType baseType) { 925 return null; 926 } 927 928 /* 929 /********************************************************** 930 /* Serialization: class annotations 931 /********************************************************** 932 */ 933 934 @Override findSerializationPropertyOrder(AnnotatedClass ac)935 public String[] findSerializationPropertyOrder(AnnotatedClass ac) { 936 JsonPropertyOrder order = _findAnnotation(ac, JsonPropertyOrder.class); 937 return (order == null) ? null : order.value(); 938 } 939 940 @Override findSerializationSortAlphabetically(Annotated ann)941 public Boolean findSerializationSortAlphabetically(Annotated ann) { 942 return _findSortAlpha(ann); 943 } 944 _findSortAlpha(Annotated ann)945 private final Boolean _findSortAlpha(Annotated ann) { 946 JsonPropertyOrder order = _findAnnotation(ann, JsonPropertyOrder.class); 947 // 23-Jun-2015, tatu: as per [databind#840], let's only consider 948 // `true` to have any significance. 949 if ((order != null) && order.alphabetic()) { 950 return Boolean.TRUE; 951 } 952 return null; 953 } 954 955 @Override findAndAddVirtualProperties(MapperConfig<?> config, AnnotatedClass ac, List<BeanPropertyWriter> properties)956 public void findAndAddVirtualProperties(MapperConfig<?> config, AnnotatedClass ac, 957 List<BeanPropertyWriter> properties) { 958 JsonAppend ann = _findAnnotation(ac, JsonAppend.class); 959 if (ann == null) { 960 return; 961 } 962 final boolean prepend = ann.prepend(); 963 JavaType propType = null; 964 965 // First: any attribute-backed properties? 966 JsonAppend.Attr[] attrs = ann.attrs(); 967 for (int i = 0, len = attrs.length; i < len; ++i) { 968 if (propType == null) { 969 propType = config.constructType(Object.class); 970 } 971 BeanPropertyWriter bpw = _constructVirtualProperty(attrs[i], 972 config, ac, propType); 973 if (prepend) { 974 properties.add(i, bpw); 975 } else { 976 properties.add(bpw); 977 } 978 } 979 980 // Then: general-purpose virtual properties? 981 JsonAppend.Prop[] props = ann.props(); 982 for (int i = 0, len = props.length; i < len; ++i) { 983 BeanPropertyWriter bpw = _constructVirtualProperty(props[i], 984 config, ac); 985 if (prepend) { 986 properties.add(i, bpw); 987 } else { 988 properties.add(bpw); 989 } 990 } 991 } 992 _constructVirtualProperty(JsonAppend.Attr attr, MapperConfig<?> config, AnnotatedClass ac, JavaType type)993 protected BeanPropertyWriter _constructVirtualProperty(JsonAppend.Attr attr, 994 MapperConfig<?> config, AnnotatedClass ac, JavaType type) 995 { 996 PropertyMetadata metadata = attr.required() ? 997 PropertyMetadata.STD_REQUIRED : PropertyMetadata.STD_OPTIONAL; 998 // could add Index, Description in future, if those matter 999 String attrName = attr.value(); 1000 1001 // allow explicit renaming; if none, default to attribute name 1002 PropertyName propName = _propertyName(attr.propName(), attr.propNamespace()); 1003 if (!propName.hasSimpleName()) { 1004 propName = PropertyName.construct(attrName); 1005 } 1006 // now, then, we need a placeholder for member (no real Field/Method): 1007 AnnotatedMember member = new VirtualAnnotatedMember(ac, ac.getRawType(), 1008 attrName, type); 1009 // and with that and property definition 1010 SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(config, 1011 member, propName, metadata, attr.include()); 1012 // can construct the property writer 1013 return AttributePropertyWriter.construct(attrName, propDef, 1014 ac.getAnnotations(), type); 1015 } 1016 _constructVirtualProperty(JsonAppend.Prop prop, MapperConfig<?> config, AnnotatedClass ac)1017 protected BeanPropertyWriter _constructVirtualProperty(JsonAppend.Prop prop, 1018 MapperConfig<?> config, AnnotatedClass ac) 1019 { 1020 PropertyMetadata metadata = prop.required() ? 1021 PropertyMetadata.STD_REQUIRED : PropertyMetadata.STD_OPTIONAL; 1022 PropertyName propName = _propertyName(prop.name(), prop.namespace()); 1023 JavaType type = config.constructType(prop.type()); 1024 // now, then, we need a placeholder for member (no real Field/Method): 1025 AnnotatedMember member = new VirtualAnnotatedMember(ac, ac.getRawType(), 1026 propName.getSimpleName(), type); 1027 // and with that and property definition 1028 SimpleBeanPropertyDefinition propDef = SimpleBeanPropertyDefinition.construct(config, 1029 member, propName, metadata, prop.include()); 1030 1031 Class<?> implClass = prop.value(); 1032 1033 HandlerInstantiator hi = config.getHandlerInstantiator(); 1034 VirtualBeanPropertyWriter bpw = (hi == null) ? null 1035 : hi.virtualPropertyWriterInstance(config, implClass); 1036 if (bpw == null) { 1037 bpw = (VirtualBeanPropertyWriter) ClassUtil.createInstance(implClass, 1038 config.canOverrideAccessModifiers()); 1039 } 1040 1041 // one more thing: give it necessary contextual information 1042 return bpw.withConfig(config, ac, propDef, type); 1043 } 1044 1045 /* 1046 /********************************************************** 1047 /* Serialization: property annotations 1048 /********************************************************** 1049 */ 1050 1051 @Override findNameForSerialization(Annotated a)1052 public PropertyName findNameForSerialization(Annotated a) 1053 { 1054 boolean useDefault = false; 1055 JsonGetter jg = _findAnnotation(a, JsonGetter.class); 1056 if (jg != null) { 1057 String s = jg.value(); 1058 // 04-May-2018, tatu: Should allow for "nameless" `@JsonGetter` too 1059 if (!s.isEmpty()) { 1060 return PropertyName.construct(s); 1061 } 1062 useDefault = true; 1063 } 1064 JsonProperty pann = _findAnnotation(a, JsonProperty.class); 1065 if (pann != null) { 1066 return PropertyName.construct(pann.value()); 1067 } 1068 if (useDefault || _hasOneOf(a, ANNOTATIONS_TO_INFER_SER)) { 1069 return PropertyName.USE_DEFAULT; 1070 } 1071 return null; 1072 } 1073 1074 @Override // since 2.9 hasAsValue(Annotated a)1075 public Boolean hasAsValue(Annotated a) { 1076 JsonValue ann = _findAnnotation(a, JsonValue.class); 1077 if (ann == null) { 1078 return null; 1079 } 1080 return ann.value(); 1081 } 1082 1083 @Override // since 2.9 hasAnyGetter(Annotated a)1084 public Boolean hasAnyGetter(Annotated a) { 1085 JsonAnyGetter ann = _findAnnotation(a, JsonAnyGetter.class); 1086 if (ann == null) { 1087 return null; 1088 } 1089 return ann.enabled(); 1090 } 1091 1092 @Override 1093 @Deprecated // since 2.9 hasAnyGetterAnnotation(AnnotatedMethod am)1094 public boolean hasAnyGetterAnnotation(AnnotatedMethod am) { 1095 // No dedicated disabling; regular @JsonIgnore used if needs to be ignored (handled separately) 1096 return _hasAnnotation(am, JsonAnyGetter.class); 1097 } 1098 1099 @Override 1100 @Deprecated // since 2.9 hasAsValueAnnotation(AnnotatedMethod am)1101 public boolean hasAsValueAnnotation(AnnotatedMethod am) { 1102 JsonValue ann = _findAnnotation(am, JsonValue.class); 1103 // value of 'false' means disabled... 1104 return (ann != null) && ann.value(); 1105 } 1106 1107 /* 1108 /********************************************************** 1109 /* Deserialization: general annotations 1110 /********************************************************** 1111 */ 1112 1113 @Override findDeserializer(Annotated a)1114 public Object findDeserializer(Annotated a) 1115 { 1116 JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class); 1117 if (ann != null) { 1118 @SuppressWarnings("rawtypes") 1119 Class<? extends JsonDeserializer> deserClass = ann.using(); 1120 if (deserClass != JsonDeserializer.None.class) { 1121 return deserClass; 1122 } 1123 } 1124 return null; 1125 } 1126 1127 @Override findKeyDeserializer(Annotated a)1128 public Object findKeyDeserializer(Annotated a) 1129 { 1130 JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class); 1131 if (ann != null) { 1132 Class<? extends KeyDeserializer> deserClass = ann.keyUsing(); 1133 if (deserClass != KeyDeserializer.None.class) { 1134 return deserClass; 1135 } 1136 } 1137 return null; 1138 } 1139 1140 @Override findContentDeserializer(Annotated a)1141 public Object findContentDeserializer(Annotated a) 1142 { 1143 JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class); 1144 if (ann != null) { 1145 @SuppressWarnings("rawtypes") 1146 Class<? extends JsonDeserializer> deserClass = ann.contentUsing(); 1147 if (deserClass != JsonDeserializer.None.class) { 1148 return deserClass; 1149 } 1150 } 1151 return null; 1152 } 1153 1154 @Override findDeserializationConverter(Annotated a)1155 public Object findDeserializationConverter(Annotated a) 1156 { 1157 JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class); 1158 return (ann == null) ? null : _classIfExplicit(ann.converter(), Converter.None.class); 1159 } 1160 1161 @Override findDeserializationContentConverter(AnnotatedMember a)1162 public Object findDeserializationContentConverter(AnnotatedMember a) 1163 { 1164 JsonDeserialize ann = _findAnnotation(a, JsonDeserialize.class); 1165 return (ann == null) ? null : _classIfExplicit(ann.contentConverter(), Converter.None.class); 1166 } 1167 1168 /* 1169 /********************************************************** 1170 /* Deserialization: type modifications 1171 /********************************************************** 1172 */ 1173 1174 @Override refineDeserializationType(final MapperConfig<?> config, final Annotated a, final JavaType baseType)1175 public JavaType refineDeserializationType(final MapperConfig<?> config, 1176 final Annotated a, final JavaType baseType) throws JsonMappingException 1177 { 1178 JavaType type = baseType; 1179 final TypeFactory tf = config.getTypeFactory(); 1180 1181 final JsonDeserialize jsonDeser = _findAnnotation(a, JsonDeserialize.class); 1182 1183 // Ok: start by refining the main type itself; common to all types 1184 final Class<?> valueClass = (jsonDeser == null) ? null : _classIfExplicit(jsonDeser.as()); 1185 if ((valueClass != null) && !type.hasRawClass(valueClass) 1186 && !_primitiveAndWrapper(type, valueClass)) { 1187 try { 1188 type = tf.constructSpecializedType(type, valueClass); 1189 } catch (IllegalArgumentException iae) { 1190 throw new JsonMappingException(null, 1191 String.format("Failed to narrow type %s with annotation (value %s), from '%s': %s", 1192 type, valueClass.getName(), a.getName(), iae.getMessage()), 1193 iae); 1194 } 1195 } 1196 // Then further processing for container types 1197 1198 // First, key type (for Maps, Map-like types): 1199 if (type.isMapLikeType()) { 1200 JavaType keyType = type.getKeyType(); 1201 final Class<?> keyClass = (jsonDeser == null) ? null : _classIfExplicit(jsonDeser.keyAs()); 1202 if ((keyClass != null) 1203 && !_primitiveAndWrapper(keyType, keyClass)) { 1204 try { 1205 keyType = tf.constructSpecializedType(keyType, keyClass); 1206 type = ((MapLikeType) type).withKeyType(keyType); 1207 } catch (IllegalArgumentException iae) { 1208 throw new JsonMappingException(null, 1209 String.format("Failed to narrow key type of %s with concrete-type annotation (value %s), from '%s': %s", 1210 type, keyClass.getName(), a.getName(), iae.getMessage()), 1211 iae); 1212 } 1213 } 1214 } 1215 JavaType contentType = type.getContentType(); 1216 if (contentType != null) { // collection[like], map[like], array, reference 1217 // And then value types for all containers: 1218 final Class<?> contentClass = (jsonDeser == null) ? null : _classIfExplicit(jsonDeser.contentAs()); 1219 if ((contentClass != null) 1220 && !_primitiveAndWrapper(contentType, contentClass)) { 1221 try { 1222 contentType = tf.constructSpecializedType(contentType, contentClass); 1223 type = type.withContentType(contentType); 1224 } catch (IllegalArgumentException iae) { 1225 throw new JsonMappingException(null, 1226 String.format("Failed to narrow value type of %s with concrete-type annotation (value %s), from '%s': %s", 1227 type, contentClass.getName(), a.getName(), iae.getMessage()), 1228 iae); 1229 } 1230 } 1231 } 1232 return type; 1233 } 1234 1235 @Override 1236 @Deprecated // since 2.7 findDeserializationContentType(Annotated am, JavaType baseContentType)1237 public Class<?> findDeserializationContentType(Annotated am, JavaType baseContentType) { 1238 return null; 1239 } 1240 1241 @Override 1242 @Deprecated // since 2.7 findDeserializationType(Annotated am, JavaType baseType)1243 public Class<?> findDeserializationType(Annotated am, JavaType baseType) { 1244 return null; 1245 } 1246 1247 @Override 1248 @Deprecated // since 2.7 findDeserializationKeyType(Annotated am, JavaType baseKeyType)1249 public Class<?> findDeserializationKeyType(Annotated am, JavaType baseKeyType) { 1250 return null; 1251 } 1252 1253 /* 1254 /********************************************************** 1255 /* Deserialization: Class annotations 1256 /********************************************************** 1257 */ 1258 1259 @Override findValueInstantiator(AnnotatedClass ac)1260 public Object findValueInstantiator(AnnotatedClass ac) 1261 { 1262 JsonValueInstantiator ann = _findAnnotation(ac, JsonValueInstantiator.class); 1263 // no 'null' marker yet, so: 1264 return (ann == null) ? null : ann.value(); 1265 } 1266 1267 @Override findPOJOBuilder(AnnotatedClass ac)1268 public Class<?> findPOJOBuilder(AnnotatedClass ac) 1269 { 1270 JsonDeserialize ann = _findAnnotation(ac, JsonDeserialize.class); 1271 return (ann == null) ? null : _classIfExplicit(ann.builder()); 1272 } 1273 1274 @Override findPOJOBuilderConfig(AnnotatedClass ac)1275 public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) 1276 { 1277 JsonPOJOBuilder ann = _findAnnotation(ac, JsonPOJOBuilder.class); 1278 return (ann == null) ? null : new JsonPOJOBuilder.Value(ann); 1279 } 1280 1281 /* 1282 /********************************************************** 1283 /* Deserialization: property annotations 1284 /********************************************************** 1285 */ 1286 1287 @Override findNameForDeserialization(Annotated a)1288 public PropertyName findNameForDeserialization(Annotated a) 1289 { 1290 // @JsonSetter has precedence over @JsonProperty, being more specific 1291 1292 boolean useDefault = false; 1293 JsonSetter js = _findAnnotation(a, JsonSetter.class); 1294 if (js != null) { 1295 String s = js.value(); 1296 // 04-May-2018, tatu: Need to allow for "nameless" `@JsonSetter` too 1297 if (s.isEmpty()) { 1298 useDefault = true; 1299 } else { 1300 return PropertyName.construct(s); 1301 } 1302 } 1303 JsonProperty pann = _findAnnotation(a, JsonProperty.class); 1304 if (pann != null) { 1305 return PropertyName.construct(pann.value()); 1306 } 1307 if (useDefault || _hasOneOf(a, ANNOTATIONS_TO_INFER_DESER)) { 1308 return PropertyName.USE_DEFAULT; 1309 } 1310 return null; 1311 } 1312 1313 @Override hasAnySetter(Annotated a)1314 public Boolean hasAnySetter(Annotated a) { 1315 JsonAnySetter ann = _findAnnotation(a, JsonAnySetter.class); 1316 return (ann == null) ? null : ann.enabled(); 1317 } 1318 1319 @Override findSetterInfo(Annotated a)1320 public JsonSetter.Value findSetterInfo(Annotated a) { 1321 return JsonSetter.Value.from(_findAnnotation(a, JsonSetter.class)); 1322 } 1323 1324 @Override // since 2.9 findMergeInfo(Annotated a)1325 public Boolean findMergeInfo(Annotated a) { 1326 JsonMerge ann = _findAnnotation(a, JsonMerge.class); 1327 return (ann == null) ? null : ann.value().asBoolean(); 1328 } 1329 1330 @Override 1331 @Deprecated // since 2.9 hasAnySetterAnnotation(AnnotatedMethod am)1332 public boolean hasAnySetterAnnotation(AnnotatedMethod am) { 1333 return _hasAnnotation(am, JsonAnySetter.class); 1334 } 1335 1336 @Override 1337 @Deprecated // since 2.9 hasCreatorAnnotation(Annotated a)1338 public boolean hasCreatorAnnotation(Annotated a) 1339 { 1340 /* No dedicated disabling; regular @JsonIgnore used if needs to be 1341 * ignored (and if so, is handled prior to this method getting called) 1342 */ 1343 JsonCreator ann = _findAnnotation(a, JsonCreator.class); 1344 if (ann != null) { 1345 return (ann.mode() != JsonCreator.Mode.DISABLED); 1346 } 1347 // 19-Apr-2016, tatu: As per [databind#1197], [databind#1122] (and some related), 1348 // may or may not consider it a creator 1349 if (_cfgConstructorPropertiesImpliesCreator ) { 1350 if (a instanceof AnnotatedConstructor) { 1351 if (_java7Helper != null) { 1352 Boolean b = _java7Helper.hasCreatorAnnotation(a); 1353 if (b != null) { 1354 return b.booleanValue(); 1355 } 1356 } 1357 } 1358 } 1359 return false; 1360 } 1361 1362 @Override 1363 @Deprecated // since 2.9 findCreatorBinding(Annotated a)1364 public JsonCreator.Mode findCreatorBinding(Annotated a) { 1365 JsonCreator ann = _findAnnotation(a, JsonCreator.class); 1366 return (ann == null) ? null : ann.mode(); 1367 } 1368 1369 @Override findCreatorAnnotation(MapperConfig<?> config, Annotated a)1370 public JsonCreator.Mode findCreatorAnnotation(MapperConfig<?> config, Annotated a) { 1371 JsonCreator ann = _findAnnotation(a, JsonCreator.class); 1372 if (ann != null) { 1373 return ann.mode(); 1374 } 1375 if (_cfgConstructorPropertiesImpliesCreator 1376 && config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES) 1377 ) { 1378 if (a instanceof AnnotatedConstructor) { 1379 if (_java7Helper != null) { 1380 Boolean b = _java7Helper.hasCreatorAnnotation(a); 1381 if ((b != null) && b.booleanValue()) { 1382 // 13-Sep-2016, tatu: Judgment call, but I don't think JDK ever implies 1383 // use of delegate; assumes as-properties implicitly 1384 return JsonCreator.Mode.PROPERTIES; 1385 } 1386 } 1387 } 1388 } 1389 return null; 1390 } 1391 1392 /* 1393 /********************************************************** 1394 /* Helper methods 1395 /********************************************************** 1396 */ 1397 _isIgnorable(Annotated a)1398 protected boolean _isIgnorable(Annotated a) 1399 { 1400 JsonIgnore ann = _findAnnotation(a, JsonIgnore.class); 1401 if (ann != null) { 1402 return ann.value(); 1403 } 1404 if (_java7Helper != null) { 1405 Boolean b = _java7Helper.findTransient(a); 1406 if (b != null) { 1407 return b.booleanValue(); 1408 } 1409 } 1410 return false; 1411 } 1412 _classIfExplicit(Class<?> cls)1413 protected Class<?> _classIfExplicit(Class<?> cls) { 1414 if (cls == null || ClassUtil.isBogusClass(cls)) { 1415 return null; 1416 } 1417 return cls; 1418 } 1419 _classIfExplicit(Class<?> cls, Class<?> implicit)1420 protected Class<?> _classIfExplicit(Class<?> cls, Class<?> implicit) { 1421 cls = _classIfExplicit(cls); 1422 return (cls == null || cls == implicit) ? null : cls; 1423 } 1424 _propertyName(String localName, String namespace)1425 protected PropertyName _propertyName(String localName, String namespace) { 1426 if (localName.isEmpty()) { 1427 return PropertyName.USE_DEFAULT; 1428 } 1429 if (namespace == null || namespace.isEmpty()) { 1430 return PropertyName.construct(localName); 1431 } 1432 return PropertyName.construct(localName, namespace); 1433 } 1434 _findConstructorName(Annotated a)1435 protected PropertyName _findConstructorName(Annotated a) 1436 { 1437 if (a instanceof AnnotatedParameter) { 1438 AnnotatedParameter p = (AnnotatedParameter) a; 1439 AnnotatedWithParams ctor = p.getOwner(); 1440 1441 if (ctor != null) { 1442 if (_java7Helper != null) { 1443 PropertyName name = _java7Helper.findConstructorName(p); 1444 if (name != null) { 1445 return name; 1446 } 1447 } 1448 } 1449 } 1450 return null; 1451 } 1452 1453 /** 1454 * Helper method called to construct and initialize instance of {@link TypeResolverBuilder} 1455 * if given annotated element indicates one is needed. 1456 */ 1457 @SuppressWarnings("deprecation") _findTypeResolver(MapperConfig<?> config, Annotated ann, JavaType baseType)1458 protected TypeResolverBuilder<?> _findTypeResolver(MapperConfig<?> config, 1459 Annotated ann, JavaType baseType) 1460 { 1461 // First: maybe we have explicit type resolver? 1462 TypeResolverBuilder<?> b; 1463 JsonTypeInfo info = _findAnnotation(ann, JsonTypeInfo.class); 1464 JsonTypeResolver resAnn = _findAnnotation(ann, JsonTypeResolver.class); 1465 1466 if (resAnn != null) { 1467 if (info == null) { 1468 return null; 1469 } 1470 // let's not try to force access override (would need to pass 1471 // settings through if we did, since that's not doable on some platforms) 1472 b = config.typeResolverBuilderInstance(ann, resAnn.value()); 1473 } else { // if not, use standard one, if indicated by annotations 1474 if (info == null) { 1475 return null; 1476 } 1477 // bit special; must return 'marker' to block use of default typing: 1478 if (info.use() == JsonTypeInfo.Id.NONE) { 1479 return _constructNoTypeResolverBuilder(); 1480 } 1481 b = _constructStdTypeResolverBuilder(); 1482 } 1483 // Does it define a custom type id resolver? 1484 JsonTypeIdResolver idResInfo = _findAnnotation(ann, JsonTypeIdResolver.class); 1485 TypeIdResolver idRes = (idResInfo == null) ? null 1486 : config.typeIdResolverInstance(ann, idResInfo.value()); 1487 if (idRes != null) { 1488 idRes.init(baseType); 1489 } 1490 b = b.init(info.use(), idRes); 1491 // 13-Aug-2011, tatu: One complication; external id only works for properties; 1492 // so if declared for a Class, we will need to map it to "PROPERTY" 1493 // instead of "EXTERNAL_PROPERTY" 1494 JsonTypeInfo.As inclusion = info.include(); 1495 if (inclusion == JsonTypeInfo.As.EXTERNAL_PROPERTY && (ann instanceof AnnotatedClass)) { 1496 inclusion = JsonTypeInfo.As.PROPERTY; 1497 } 1498 b = b.inclusion(inclusion); 1499 b = b.typeProperty(info.property()); 1500 Class<?> defaultImpl = info.defaultImpl(); 1501 1502 // 08-Dec-2014, tatu: To deprecate `JsonTypeInfo.None` we need to use other placeholder(s); 1503 // and since `java.util.Void` has other purpose (to indicate "deser as null"), we'll instead 1504 // use `JsonTypeInfo.class` itself. But any annotation type will actually do, as they have no 1505 // valid use (cannot instantiate as default) 1506 if (defaultImpl != JsonTypeInfo.None.class && !defaultImpl.isAnnotation()) { 1507 b = b.defaultImpl(defaultImpl); 1508 } 1509 b = b.typeIdVisibility(info.visible()); 1510 return b; 1511 } 1512 1513 /** 1514 * Helper method for constructing standard {@link TypeResolverBuilder} 1515 * implementation. 1516 */ _constructStdTypeResolverBuilder()1517 protected StdTypeResolverBuilder _constructStdTypeResolverBuilder() { 1518 return new StdTypeResolverBuilder(); 1519 } 1520 1521 /** 1522 * Helper method for dealing with "no type info" marker; can't be null 1523 * (as it'd be replaced by default typing) 1524 */ _constructNoTypeResolverBuilder()1525 protected StdTypeResolverBuilder _constructNoTypeResolverBuilder() { 1526 return StdTypeResolverBuilder.noTypeInfoBuilder(); 1527 } 1528 _primitiveAndWrapper(Class<?> baseType, Class<?> refinement)1529 private boolean _primitiveAndWrapper(Class<?> baseType, Class<?> refinement) 1530 { 1531 if (baseType.isPrimitive()) { 1532 return baseType == ClassUtil.primitiveType(refinement); 1533 } 1534 if (refinement.isPrimitive()) { 1535 return refinement == ClassUtil.primitiveType(baseType); 1536 } 1537 return false; 1538 } 1539 _primitiveAndWrapper(JavaType baseType, Class<?> refinement)1540 private boolean _primitiveAndWrapper(JavaType baseType, Class<?> refinement) 1541 { 1542 if (baseType.isPrimitive()) { 1543 return baseType.hasRawClass(ClassUtil.primitiveType(refinement)); 1544 } 1545 if (refinement.isPrimitive()) { 1546 return refinement == ClassUtil.primitiveType(baseType.getRawClass()); 1547 } 1548 return false; 1549 } 1550 } 1551