Skip to content

Commit ab53ab4

Browse files
committed
Implemented #438
1 parent b85ddf0 commit ab53ab4

File tree

10 files changed

+216
-243
lines changed

10 files changed

+216
-243
lines changed

release-notes/VERSION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Version: 2.4.0 (xx-xxx-2014)
2828
(contributed by Francis G)
2929
#435: Performance bottleneck in TypeFactory._fromClass
3030
(reported by sdonovanuk@github)
31+
#438: Add support for accessing `@JsonProperty(index=N)` annotations
3132

3233
------------------------------------------------------------------------
3334
=== History: ===

src/main/java/com/fasterxml/jackson/databind/AnnotationIntrospector.java

Lines changed: 32 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,7 @@ public String[] findPropertiesToIgnore(Annotated ac) {
231231
/**
232232
* Method for checking whether an annotation indicates that all unknown properties
233233
*/
234-
public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) {
235-
return null;
236-
}
234+
public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) { return null; }
237235

238236
/**
239237
* Method for checking whether properties that have specified type
@@ -246,17 +244,13 @@ public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) {
246244
* Boolean.FALSE if they are not to be ignored, null for default
247245
* handling (which is 'do not ignore')
248246
*/
249-
public Boolean isIgnorableType(AnnotatedClass ac) {
250-
return null;
251-
}
247+
public Boolean isIgnorableType(AnnotatedClass ac) { return null; }
252248

253249
/**
254250
* @deprecated Since 2.3: use the one that takes generic {@link Annotated}
255251
*/
256252
@Deprecated
257-
public Object findFilterId(AnnotatedClass ac) {
258-
return findFilterId((Annotated) ac);
259-
}
253+
public Object findFilterId(AnnotatedClass ac) { return findFilterId((Annotated) ac); }
260254

261255
/**
262256
* Method for finding if annotated class has associated filter; and if so,
@@ -265,9 +259,7 @@ public Object findFilterId(AnnotatedClass ac) {
265259
* @return Id of the filter to use for filtering properties of annotated
266260
* class, if any; or null if none found.
267261
*/
268-
public Object findFilterId(Annotated ann) {
269-
return null;
270-
}
262+
public Object findFilterId(Annotated ann) { return null; }
271263

272264
/**
273265
* Method for finding {@link PropertyNamingStrategy} for given
@@ -280,9 +272,7 @@ public Object findFilterId(Annotated ann) {
280272
*
281273
* @since 2.1
282274
*/
283-
public Object findNamingStrategy(AnnotatedClass ac) {
284-
return null;
285-
}
275+
public Object findNamingStrategy(AnnotatedClass ac) { return null; }
286276

287277
/*
288278
/**********************************************************
@@ -297,8 +287,7 @@ public Object findNamingStrategy(AnnotatedClass ac) {
297287
* (if no annotations are found), or build and return a derived instance (using
298288
* checker's build methods).
299289
*/
300-
public VisibilityChecker<?> findAutoDetectVisibility(AnnotatedClass ac,
301-
VisibilityChecker<?> checker) {
290+
public VisibilityChecker<?> findAutoDetectVisibility(AnnotatedClass ac, VisibilityChecker<?> checker) {
302291
return checker;
303292
}
304293

@@ -378,18 +367,14 @@ public TypeResolverBuilder<?> findPropertyContentTypeResolver(MapperConfig<?> co
378367
*
379368
* @param a Annotated entity (class, field/method) to check for annotations
380369
*/
381-
public List<NamedType> findSubtypes(Annotated a) {
382-
return null;
383-
}
370+
public List<NamedType> findSubtypes(Annotated a) { return null; }
384371

385372
/**
386373
* Method for checking if specified type has explicit name.
387374
*
388375
* @param ac Class to check for type name annotations
389376
*/
390-
public String findTypeName(AnnotatedClass ac) {
391-
return null;
392-
}
377+
public String findTypeName(AnnotatedClass ac) { return null; }
393378

394379
/*
395380
/**********************************************************
@@ -401,9 +386,7 @@ public String findTypeName(AnnotatedClass ac) {
401386
* Method for checking if given member indicates that it is part
402387
* of a reference (parent/child).
403388
*/
404-
public ReferenceProperty findReferenceType(AnnotatedMember member) {
405-
return null;
406-
}
389+
public ReferenceProperty findReferenceType(AnnotatedMember member) { return null; }
407390

408391
/**
409392
* Method called to check whether given property is marked to be "unwrapped"
@@ -413,9 +396,7 @@ public ReferenceProperty findReferenceType(AnnotatedMember member) {
413396
* should be done, or null if not -- note that transformation may simply
414397
* be identity transformation (no changes).
415398
*/
416-
public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member) {
417-
return null;
418-
}
399+
public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member) { return null; }
419400

420401
/**
421402
* Method called to check whether given property is marked to
@@ -424,9 +405,7 @@ public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member) {
424405
* annotations from multiple accessors (getters, setters, fields,
425406
* constructor parameters).
426407
*/
427-
public boolean hasIgnoreMarker(AnnotatedMember m) {
428-
return false;
429-
}
408+
public boolean hasIgnoreMarker(AnnotatedMember m) { return false; }
430409

431410
/**
432411
* Method called to find out whether given member expectes a value
@@ -441,9 +420,7 @@ public boolean hasIgnoreMarker(AnnotatedMember m) {
441420
* @return Identifier of value to inject, if any; null if no injection
442421
* indicator is found
443422
*/
444-
public Object findInjectableValueId(AnnotatedMember m) {
445-
return null;
446-
}
423+
public Object findInjectableValueId(AnnotatedMember m) { return null; }
447424

448425
/**
449426
* Method that can be called to check whether this member has
@@ -452,9 +429,7 @@ public Object findInjectableValueId(AnnotatedMember m) {
452429
*
453430
* @since 2.0
454431
*/
455-
public Boolean hasRequiredMarker(AnnotatedMember m) {
456-
return null;
457-
}
432+
public Boolean hasRequiredMarker(AnnotatedMember m) { return null; }
458433

459434
/**
460435
* Method for checking if annotated property (represented by a field or
@@ -469,9 +444,7 @@ public Boolean hasRequiredMarker(AnnotatedMember m) {
469444
* @return Array of views (represented by classes) that the property is included in;
470445
* if null, always included (same as returning array containing <code>Object.class</code>)
471446
*/
472-
public Class<?>[] findViews(Annotated a) {
473-
return null;
474-
}
447+
public Class<?>[] findViews(Annotated a) { return null; }
475448

476449
/**
477450
* Method for finding format annotations for property or class.
@@ -481,21 +454,14 @@ public Class<?>[] findViews(Annotated a) {
481454
*
482455
* @since 2.1
483456
*/
484-
public JsonFormat.Value findFormat(Annotated memberOrClass) {
485-
return null;
486-
}
457+
public JsonFormat.Value findFormat(Annotated memberOrClass) { return null; }
487458

488459
/**
489460
* Method for checking whether given accessor claims to represent
490461
* type id: if so, its value may be used as an override,
491462
* instead of generated type id.
492-
*
493-
* @since 2.0
494463
*/
495-
public Boolean isTypeId(AnnotatedMember member) {
496-
return null;
497-
}
498-
464+
public Boolean isTypeId(AnnotatedMember member) { return null; }
499465

500466
/**
501467
* Method used to check if specified property has annotation that indicates
@@ -508,9 +474,7 @@ public Boolean isTypeId(AnnotatedMember member) {
508474
*
509475
* @since 2.1
510476
*/
511-
public PropertyName findWrapperName(Annotated ann) {
512-
return null;
513-
}
477+
public PropertyName findWrapperName(Annotated ann) { return null; }
514478

515479
/**
516480
* Method used to check whether specified property member (accessor
@@ -522,10 +486,21 @@ public PropertyName findWrapperName(Annotated ann) {
522486
*
523487
* @since 2.3
524488
*/
525-
public String findPropertyDescription(Annotated ann) {
526-
return null;
527-
}
528-
489+
public String findPropertyDescription(Annotated ann) { return null; }
490+
491+
/**
492+
* Method used to check whether specified property member (accessor
493+
* or mutator) defines numeric index, and if so, what is the index value.
494+
* Possible use cases for index values included use by underlying data format
495+
* (some binary formats mandate use of index instead of name) and ordering
496+
* of properties (for documentation, or during serialization).
497+
*
498+
* @since 2.4
499+
*
500+
* @return Explicitly specified index for the property, if any
501+
*/
502+
public Integer findPropertyIndex(Annotated ann) { return null; }
503+
529504
/*
530505
/**********************************************************
531506
/* Serialization: general annotations

src/main/java/com/fasterxml/jackson/databind/BeanDescription.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ public abstract class BeanDescription
3939
/**********************************************************
4040
*/
4141

42-
protected BeanDescription(JavaType type)
43-
{
42+
protected BeanDescription(JavaType type) {
4443
_type = type;
4544
}
4645

src/main/java/com/fasterxml/jackson/databind/BeanProperty.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public interface BeanProperty extends Named
6060
* Accessor for additional optional information about property.
6161
*
6262
* @since 2.3
63+
*
64+
* @return Metadata about property; never null.
6365
*/
6466
public PropertyMetadata getMetadata();
6567

src/main/java/com/fasterxml/jackson/databind/PropertyMetadata.java

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Simple container class used for storing "additional" metadata about
55
* properties. Carved out to reduce number of distinct properties that
66
* actual property implementations and placeholders need to store;
7-
* since this instances are immutable, they can be freely shared.
7+
* since instances are immutable, they can be freely shared.
88
*
99
* @since 2.3
1010
*/
@@ -13,11 +13,11 @@ public class PropertyMetadata
1313
{
1414
private static final long serialVersionUID = -1;
1515

16-
public final static PropertyMetadata STD_REQUIRED = new PropertyMetadata(Boolean.TRUE, null);
16+
public final static PropertyMetadata STD_REQUIRED = new PropertyMetadata(Boolean.TRUE, null, null);
1717

18-
public final static PropertyMetadata STD_OPTIONAL = new PropertyMetadata(Boolean.FALSE, null);
18+
public final static PropertyMetadata STD_OPTIONAL = new PropertyMetadata(Boolean.FALSE, null, null);
1919

20-
public final static PropertyMetadata STD_REQUIRED_OR_OPTIONAL = new PropertyMetadata(null, null);
20+
public final static PropertyMetadata STD_REQUIRED_OR_OPTIONAL = new PropertyMetadata(null, null, null);
2121

2222
/**
2323
* Three states: required, not required and unknown; unknown represented
@@ -30,22 +30,44 @@ public class PropertyMetadata
3030
*/
3131
protected final String _description;
3232

33+
/**
34+
* Optional index of the property within containing Object.
35+
*
36+
* @since 2.4
37+
*/
38+
protected final Integer _index;
39+
3340
/*
3441
/**********************************************************
3542
/* Construction, configuration
3643
/**********************************************************
3744
*/
3845

39-
protected PropertyMetadata(Boolean req, String desc)
46+
@Deprecated // since 2.4
47+
protected PropertyMetadata(Boolean req, String desc) { this(req, desc, null); }
48+
49+
protected PropertyMetadata(Boolean req, String desc, Integer index)
4050
{
4151
_required = req;
4252
_description = desc;
53+
_index = index;
4354
}
4455

56+
/**
57+
* @since 2.4 Use variant that takes three arguments.
58+
*/
59+
@Deprecated
4560
public static PropertyMetadata construct(boolean req, String desc) {
61+
return construct(req, desc, null);
62+
}
63+
64+
public static PropertyMetadata construct(boolean req, String desc, Integer index) {
4665
PropertyMetadata md = req ? STD_REQUIRED : STD_OPTIONAL;
4766
if (desc != null) {
48-
return md.withDescription(desc);
67+
md = md.withDescription(desc);
68+
}
69+
if (index != null) {
70+
md = md.withIndex(index);
4971
}
5072
return md;
5173
}
@@ -56,7 +78,7 @@ public static PropertyMetadata construct(boolean req, String desc) {
5678
*/
5779
protected Object readResolve()
5880
{
59-
if (_description == null) {
81+
if (_description == null && _index == null) {
6082
if (_required == null) {
6183
return STD_REQUIRED_OR_OPTIONAL;
6284
}
@@ -66,9 +88,13 @@ protected Object readResolve()
6688
}
6789

6890
public PropertyMetadata withDescription(String desc) {
69-
return new PropertyMetadata(_required, desc);
91+
return new PropertyMetadata(_required, desc, _index);
7092
}
7193

94+
public PropertyMetadata withIndex(Integer index) {
95+
return new PropertyMetadata(_required, _description, index);
96+
}
97+
7298
public PropertyMetadata withRequired(Boolean b) {
7399
if (b == null) {
74100
if (_required == null) {
@@ -79,7 +105,7 @@ public PropertyMetadata withRequired(Boolean b) {
79105
return this;
80106
}
81107
}
82-
return new PropertyMetadata(b, _description);
108+
return new PropertyMetadata(b, _description, _index);
83109
}
84110

85111
/*
@@ -93,4 +119,14 @@ public PropertyMetadata withRequired(Boolean b) {
93119
public boolean isRequired() { return (_required != null) && _required.booleanValue(); }
94120

95121
public Boolean getRequired() { return _required; }
122+
123+
/**
124+
* @since 2.4
125+
*/
126+
public Integer getIndex() { return _index; }
127+
128+
/**
129+
* @since 2.4
130+
*/
131+
public boolean hasIndex() { return _index != null; }
96132
}

src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,8 @@ protected CreatorProperty constructCreatorProperty(DeserializationContext ctxt,
673673
Boolean b = (intr == null) ? null : intr.hasRequiredMarker(param);
674674
boolean req = (b != null && b.booleanValue());
675675
String desc = (intr == null) ? null : intr.findPropertyDescription(param);
676-
metadata = PropertyMetadata.construct(req, desc);
676+
Integer idx = (intr == null) ? null : intr.findPropertyIndex(param);
677+
metadata = PropertyMetadata.construct(req, desc, idx);
677678
}
678679

679680
JavaType t0 = config.getTypeFactory().constructType(param.getParameterType(), beanDesc.bindingsForBeanType());

0 commit comments

Comments
 (0)