1 package com.fasterxml.jackson.databind; 2 3 import java.lang.annotation.Annotation; 4 import java.util.Collections; 5 import java.util.List; 6 7 import com.fasterxml.jackson.annotation.JsonFormat; 8 import com.fasterxml.jackson.annotation.JsonFormat.Value; 9 import com.fasterxml.jackson.annotation.JsonInclude; 10 11 import com.fasterxml.jackson.databind.cfg.MapperConfig; 12 import com.fasterxml.jackson.databind.introspect.AnnotatedMember; 13 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor; 14 import com.fasterxml.jackson.databind.type.TypeFactory; 15 import com.fasterxml.jackson.databind.util.Annotations; 16 import com.fasterxml.jackson.databind.util.Named; 17 18 /** 19 * Bean properties are logical entities that represent data 20 * that Java objects (POJOs (Plain Old Java Objects), sometimes also called "beans") 21 * contain; and that are accessed using accessors (methods like getters 22 * and setters, fields, constructor parameters). 23 * Instances allow access to annotations directly associated 24 * to property (via field or method), as well as contextual 25 * annotations (annotations for class that contains properties). 26 *<p> 27 * Instances are not typically passed when constructing serializers 28 * and deserializers, but rather only passed when context 29 * is known when 30 * {@link com.fasterxml.jackson.databind.ser.ContextualSerializer} and 31 * {@link com.fasterxml.jackson.databind.deser.ContextualDeserializer} 32 * resolution occurs (<code>createContextual(...)</code> method is called). 33 * References may (need to) be retained by serializers and deserializers, 34 * especially when further resolving dependent handlers like value 35 * serializers/deserializers or structured types. 36 */ 37 public interface BeanProperty extends Named 38 { 39 public final static JsonFormat.Value EMPTY_FORMAT = new JsonFormat.Value(); 40 public final static JsonInclude.Value EMPTY_INCLUDE = JsonInclude.Value.empty(); 41 42 /** 43 * Method to get logical name of the property 44 */ 45 @Override getName()46 public String getName(); 47 48 /** 49 * Method for getting full name definition, including possible 50 * format-specific additional properties (such as namespace when 51 * using XML backend). 52 * 53 * @since 2.3 54 */ getFullName()55 public PropertyName getFullName(); 56 57 /** 58 * Method to get declared type of the property. 59 */ getType()60 public JavaType getType(); 61 62 /** 63 * If property is indicated to be wrapped, name of 64 * wrapper element to use. 65 * 66 * @since 2.2 67 */ getWrapperName()68 public PropertyName getWrapperName(); 69 70 /** 71 * Accessor for additional optional information about property. 72 * 73 * @since 2.3 74 * 75 * @return Metadata about property; never null. 76 */ getMetadata()77 public PropertyMetadata getMetadata(); 78 79 /** 80 * Whether value for property is marked as required using 81 * annotations or associated schema. 82 * Equivalent to: 83 *<code> 84 * getMetadata().isRequired() 85 *</code> 86 * 87 * @since 2.2 88 */ isRequired()89 public boolean isRequired(); 90 91 /** 92 * Accessor for checking whether there is an actual physical property 93 * behind this property abstraction or not. 94 * 95 * @since 2.7 96 */ isVirtual()97 public boolean isVirtual(); 98 99 /* 100 /********************************************************** 101 /* Access to annotation information 102 /********************************************************** 103 */ 104 105 /** 106 * Method for finding annotation associated with this property; 107 * meaning annotation associated with one of entities used to 108 * access property. 109 *<p> 110 * Note that this method should only be called for custom annotations; 111 * access to standard Jackson annotations (or ones supported by 112 * alternate {@link AnnotationIntrospector}s) should be accessed 113 * through {@link AnnotationIntrospector}. 114 */ getAnnotation(Class<A> acls)115 public <A extends Annotation> A getAnnotation(Class<A> acls); 116 117 /** 118 * Method for finding annotation associated with context of 119 * this property; usually class in which member is declared 120 * (or its subtype if processing subtype). 121 *<p> 122 * Note that this method should only be called for custom annotations; 123 * access to standard Jackson annotations (or ones supported by 124 * alternate {@link AnnotationIntrospector}s) should be accessed 125 * through {@link AnnotationIntrospector}. 126 */ getContextAnnotation(Class<A> acls)127 public <A extends Annotation> A getContextAnnotation(Class<A> acls); 128 129 /** 130 * Method for accessing primary physical entity that represents the property; 131 * annotated field, method or constructor property. 132 */ getMember()133 public AnnotatedMember getMember(); 134 135 /** 136 * Convenience method that is roughly equivalent to 137 *<pre> 138 * return intr.findFormat(getMember()); 139 *</pre> 140 * and specifically does NOT try to find per-type format defaults to merge; 141 * use {@link #findPropertyFormat} if such defaults would be useful. 142 * 143 * @since 2.6 144 * 145 * @deprecated since 2.8 use {@link #findPropertyFormat} instead. 146 */ 147 @Deprecated findFormatOverrides(AnnotationIntrospector intr)148 public JsonFormat.Value findFormatOverrides(AnnotationIntrospector intr); 149 150 /** 151 * Helper method used to look up format settings applicable to this property, 152 * considering both possible per-type configuration settings 153 * 154 * @since 2.7 155 */ findPropertyFormat(MapperConfig<?> config, Class<?> baseType)156 public JsonFormat.Value findPropertyFormat(MapperConfig<?> config, Class<?> baseType); 157 158 /** 159 * Convenience method that is roughly equivalent to 160 *<pre> 161 * return config.getAnnotationIntrospector().findPropertyInclusion(getMember()); 162 *</pre> 163 * but also considers global default settings for inclusion 164 * 165 * @since 2.7 166 */ findPropertyInclusion(MapperConfig<?> config, Class<?> baseType)167 public JsonInclude.Value findPropertyInclusion(MapperConfig<?> config, Class<?> baseType); 168 169 /** 170 * Method for accessing set of possible alternate names that are accepted 171 * during deserialization. 172 * 173 * @return List (possibly empty) of alternate names; never null 174 * 175 * @since 2.9 176 */ findAliases(MapperConfig<?> config)177 public List<PropertyName> findAliases(MapperConfig<?> config); 178 179 /* 180 /********************************************************** 181 /* Schema/introspection support 182 /********************************************************** 183 */ 184 185 /** 186 * Method that can be called to visit the type structure that this 187 * property is part of. 188 * Note that not all implementations support traversal with this 189 * method; those that do not should throw 190 * {@link UnsupportedOperationException}. 191 *<p> 192 * NOTE: Starting with 2.7, takes explicit {@link SerializerProvider} 193 * argument to reduce the need to rely on provider visitor may or may not 194 * have assigned. 195 * 196 * @param objectVisitor Visitor to used as the callback handler 197 * 198 * @since 2.2 (although signature did change in 2.7) 199 */ depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, SerializerProvider provider)200 public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, 201 SerializerProvider provider) 202 throws JsonMappingException; 203 204 /* 205 /********************************************************** 206 /* Helper classes 207 /********************************************************** 208 */ 209 210 /** 211 * Simple stand-alone implementation, useful as a placeholder 212 * or base class for more complex implementations. 213 */ 214 public static class Std implements BeanProperty, 215 java.io.Serializable // 2.9 216 { 217 private static final long serialVersionUID = 1L; 218 219 protected final PropertyName _name; 220 protected final JavaType _type; 221 protected final PropertyName _wrapperName; 222 223 protected final PropertyMetadata _metadata; 224 225 /** 226 * Physical entity (field, method or constructor argument) that 227 * is used to access value of property (or in case of constructor 228 * property, just placeholder) 229 */ 230 protected final AnnotatedMember _member; 231 Std(PropertyName name, JavaType type, PropertyName wrapperName, AnnotatedMember member, PropertyMetadata metadata)232 public Std(PropertyName name, JavaType type, PropertyName wrapperName, 233 AnnotatedMember member, PropertyMetadata metadata) 234 { 235 _name = name; 236 _type = type; 237 _wrapperName = wrapperName; 238 _metadata = metadata; 239 _member = member; 240 } 241 242 /** 243 * @deprecated Since 2.9 244 */ 245 @Deprecated Std(PropertyName name, JavaType type, PropertyName wrapperName, Annotations contextAnnotations, AnnotatedMember member, PropertyMetadata metadata)246 public Std(PropertyName name, JavaType type, PropertyName wrapperName, 247 Annotations contextAnnotations, 248 AnnotatedMember member, PropertyMetadata metadata) 249 { 250 this(name, type, wrapperName, member, metadata); 251 } 252 253 /** 254 * @since 2.6 255 */ Std(Std base, JavaType newType)256 public Std(Std base, JavaType newType) { 257 this(base._name, newType, base._wrapperName, base._member, base._metadata); 258 } 259 withType(JavaType type)260 public Std withType(JavaType type) { 261 return new Std(this, type); 262 } 263 264 @Override getAnnotation(Class<A> acls)265 public <A extends Annotation> A getAnnotation(Class<A> acls) { 266 return (_member == null) ? null : _member.getAnnotation(acls); 267 } 268 269 @Override getContextAnnotation(Class<A> acls)270 public <A extends Annotation> A getContextAnnotation(Class<A> acls) { 271 return null; 272 } 273 274 @Override 275 @Deprecated findFormatOverrides(AnnotationIntrospector intr)276 public JsonFormat.Value findFormatOverrides(AnnotationIntrospector intr) { 277 if ((_member != null) && (intr != null)) { 278 JsonFormat.Value v = intr.findFormat(_member); 279 if (v != null) { 280 return v; 281 } 282 } 283 return EMPTY_FORMAT; 284 } 285 286 @Override findPropertyFormat(MapperConfig<?> config, Class<?> baseType)287 public JsonFormat.Value findPropertyFormat(MapperConfig<?> config, Class<?> baseType) { 288 JsonFormat.Value v0 = config.getDefaultPropertyFormat(baseType); 289 AnnotationIntrospector intr = config.getAnnotationIntrospector(); 290 if ((intr == null) || (_member == null)) { 291 return v0; 292 } 293 JsonFormat.Value v = intr.findFormat(_member); 294 if (v == null) { 295 return v0; 296 } 297 return v0.withOverrides(v); 298 } 299 300 @Override findPropertyInclusion(MapperConfig<?> config, Class<?> baseType)301 public JsonInclude.Value findPropertyInclusion(MapperConfig<?> config, Class<?> baseType) 302 { 303 JsonInclude.Value v0 = config.getDefaultInclusion(baseType, _type.getRawClass()); 304 AnnotationIntrospector intr = config.getAnnotationIntrospector(); 305 if ((intr == null) || (_member == null)) { 306 return v0; 307 } 308 JsonInclude.Value v = intr.findPropertyInclusion(_member); 309 if (v == null) { 310 return v0; 311 } 312 return v0.withOverrides(v); 313 } 314 315 @Override findAliases(MapperConfig<?> config)316 public List<PropertyName> findAliases(MapperConfig<?> config) { 317 // 26-Feb-2017, tatu: Do we really need to allow actual definition? 318 // For now, let's not. 319 return Collections.emptyList(); 320 } 321 getName()322 @Override public String getName() { return _name.getSimpleName(); } getFullName()323 @Override public PropertyName getFullName() { return _name; } getType()324 @Override public JavaType getType() { return _type; } getWrapperName()325 @Override public PropertyName getWrapperName() { return _wrapperName; } isRequired()326 @Override public boolean isRequired() { return _metadata.isRequired(); } getMetadata()327 @Override public PropertyMetadata getMetadata() { return _metadata; } getMember()328 @Override public AnnotatedMember getMember() { return _member; } 329 330 @Override isVirtual()331 public boolean isVirtual() { return false; } 332 333 /** 334 * Implementation of this method throws 335 * {@link UnsupportedOperationException}, since instances of this 336 * implementation should not be used as part of actual structure 337 * visited. Rather, other implementations should handle it. 338 */ 339 @Override depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, SerializerProvider provider)340 public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, 341 SerializerProvider provider) { 342 throw new UnsupportedOperationException("Instances of "+getClass().getName()+" should not get visited"); 343 } 344 } 345 346 /** 347 * Alternative "Null" implementation that can be used in cases where a non-null 348 * {@link BeanProperty} is needed 349 * 350 * @since 2.9 351 */ 352 public static class Bogus implements BeanProperty 353 { 354 @Override getName()355 public String getName() { 356 return ""; 357 } 358 359 @Override getFullName()360 public PropertyName getFullName() { 361 return PropertyName.NO_NAME; 362 } 363 364 @Override getType()365 public JavaType getType() { 366 return TypeFactory.unknownType(); 367 } 368 369 @Override getWrapperName()370 public PropertyName getWrapperName() { 371 return null; 372 } 373 374 @Override getMetadata()375 public PropertyMetadata getMetadata() { 376 return PropertyMetadata.STD_REQUIRED_OR_OPTIONAL; 377 } 378 379 @Override isRequired()380 public boolean isRequired() { 381 return false; 382 } 383 384 @Override isVirtual()385 public boolean isVirtual() { 386 return false; 387 } 388 389 @Override getAnnotation(Class<A> acls)390 public <A extends Annotation> A getAnnotation(Class<A> acls) { 391 return null; 392 } 393 394 @Override getContextAnnotation(Class<A> acls)395 public <A extends Annotation> A getContextAnnotation(Class<A> acls) { 396 return null; 397 } 398 399 @Override getMember()400 public AnnotatedMember getMember() { 401 return null; 402 } 403 404 @Override 405 @Deprecated findFormatOverrides(AnnotationIntrospector intr)406 public Value findFormatOverrides(AnnotationIntrospector intr) { 407 return Value.empty(); 408 } 409 410 @Override findPropertyFormat(MapperConfig<?> config, Class<?> baseType)411 public Value findPropertyFormat(MapperConfig<?> config, Class<?> baseType) { 412 return Value.empty(); 413 } 414 415 @Override findPropertyInclusion( MapperConfig<?> config, Class<?> baseType)416 public com.fasterxml.jackson.annotation.JsonInclude.Value findPropertyInclusion( 417 MapperConfig<?> config, Class<?> baseType) 418 { 419 return null; 420 } 421 422 @Override findAliases(MapperConfig<?> config)423 public List<PropertyName> findAliases(MapperConfig<?> config) { 424 return Collections.emptyList(); 425 } 426 427 @Override depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, SerializerProvider provider)428 public void depositSchemaProperty(JsonObjectFormatVisitor objectVisitor, 429 SerializerProvider provider) throws JsonMappingException { 430 } 431 } 432 } 433