Skip to content

Commit ee1c51a

Browse files
committed
Fix #795
1 parent f0efb09 commit ee1c51a

File tree

7 files changed

+57
-34
lines changed

7 files changed

+57
-34
lines changed

release-notes/VERSION

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ Project: jackson-databind
4949
configurable/external equality comparison
5050
#794: Add `SerializationFeature.WRITE_DATES_WITH_ZONE_ID` to allow inclusion/exclusion of
5151
timezone id for date/time values (as opposed to timezone offset)
52+
#795: Converter annotation not honored for abstract types
53+
(reported by myrosia@github)
5254
- Remove old cglib compatibility tests; cause problems in Eclipse
5355

5456
2.5.4 (not yet released)

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,6 @@ public ValueInstantiator _valueInstantiatorInstance(DeserializationConfig config
411411

412412
// may need to keep track for [#725]
413413
List<AnnotatedConstructor> implicitCtors = null;
414-
415414
for (AnnotatedConstructor ctor : beanDesc.getConstructors()) {
416415
final boolean isCreator = intr.hasCreatorAnnotation(ctor);
417416
BeanPropertyDefinition[] propDefs = creatorParams.get(ctor);
@@ -446,7 +445,7 @@ public ValueInstantiator _valueInstantiatorInstance(DeserializationConfig config
446445
// 2 or more args; all params must have names or be injectable
447446
// 14-Mar-2015, tatu (2.6): Or, as per [#725], implicit names will also
448447
// do, with some constraints. But that will require bit post processing...
449-
448+
450449
AnnotatedParameter nonAnnotatedParam = null;
451450
CreatorProperty[] properties = new CreatorProperty[argCount];
452451
int explicitNameCount = 0;

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ public class BeanDeserializer
2020
{
2121
/* TODOs for future versions:
2222
*
23-
* For 2.6?
24-
*
23+
* For 2.7?
24+
*
2525
* - New method in JsonDeserializer (deserializeNext()) to allow use of more
2626
* efficient 'nextXxx()' method `JsonParser` provides.
2727
*
@@ -429,7 +429,7 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri
429429
unknown.writeFieldName(propName);
430430
unknown.copyCurrentStructure(p);
431431
}
432-
432+
433433
// We hit END_OBJECT, so:
434434
Object bean;
435435
try {

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

+34-7
Original file line numberDiff line numberDiff line change
@@ -407,11 +407,11 @@ public void resolve(DeserializationContext ctxt)
407407
{
408408
ExternalTypeHandler.Builder extTypes = null;
409409
// if ValueInstantiator can use "creator" approach, need to resolve it here...
410+
SettableBeanProperty[] creatorProps;
410411
if (_valueInstantiator.canCreateFromObjectWith()) {
411-
SettableBeanProperty[] creatorProps = _valueInstantiator.getFromObjectArguments(ctxt.getConfig());
412-
_propertyBasedCreator = PropertyBasedCreator.construct(ctxt, _valueInstantiator, creatorProps);
412+
creatorProps = _valueInstantiator.getFromObjectArguments(ctxt.getConfig());
413413
// also: need to try to resolve 'external' type ids...
414-
for (SettableBeanProperty prop : _propertyBasedCreator.properties()) {
414+
for (SettableBeanProperty prop : creatorProps) {
415415
if (prop.hasValueTypeDeserializer()) {
416416
TypeDeserializer typeDeser = prop.getValueTypeDeserializer();
417417
if (typeDeser.getTypeInclusion() == JsonTypeInfo.As.EXTERNAL_PROPERTY) {
@@ -422,12 +422,15 @@ public void resolve(DeserializationContext ctxt)
422422
}
423423
}
424424
}
425+
} else {
426+
creatorProps = null;
425427
}
426428

427429
UnwrappedPropertyHandler unwrapped = null;
428430

429431
for (SettableBeanProperty origProp : _beanProperties) {
430432
SettableBeanProperty prop = origProp;
433+
431434
// May already have deserializer from annotations, if so, skip:
432435
if (!prop.hasValueDeserializer()) {
433436
// [Issue#125]: allow use of converters
@@ -447,6 +450,7 @@ public void resolve(DeserializationContext ctxt)
447450
prop = prop.withValueDeserializer(cd);
448451
}
449452
}
453+
450454
// [JACKSON-235]: need to link managed references with matching back references
451455
prop = _resolveManagedReferenceProperty(ctxt, prop);
452456

@@ -472,11 +476,29 @@ public void resolve(DeserializationContext ctxt)
472476
prop = _resolveInnerClassValuedProperty(ctxt, prop);
473477
if (prop != origProp) {
474478
_beanProperties.replace(prop);
479+
// [databind#795]: Make sure PropertyBasedCreator's properties stay in sync
480+
if (creatorProps != null) {
481+
// 18-May-2015, tatu: _Should_ start with consistent set. But can we really
482+
// fully count on this? May need to revisit in future; seems to hold for now.
483+
for (int i = 0, len = creatorProps.length; i < len; ++i) {
484+
if (creatorProps[i] == origProp) {
485+
creatorProps[i] = prop;
486+
break;
487+
}
488+
// ... as per above, it is possible we'd need to add this as fallback
489+
// if (but only if) identity check fails?
490+
/*
491+
if (creatorProps[i].getName().equals(prop.getName())) {
492+
creatorProps[i] = prop;
493+
break;
494+
}
495+
*/
496+
}
497+
}
475498
}
476499

477-
/* one more thing: if this property uses "external property" type inclusion
478-
* (see [JACKSON-453]), it needs different handling altogether
479-
*/
500+
// one more thing: if this property uses "external property" type inclusion
501+
// (see [JACKSON-453]), it needs different handling altogether
480502
if (prop.hasValueTypeDeserializer()) {
481503
TypeDeserializer typeDeser = prop.getValueTypeDeserializer();
482504
if (typeDeser.getTypeInclusion() == JsonTypeInfo.As.EXTERNAL_PROPERTY) {
@@ -522,7 +544,12 @@ public void resolve(DeserializationContext ctxt)
522544
}
523545
_delegateDeserializer = dd;
524546
}
525-
547+
548+
// And now that we know CreatorProperty instances are also resolved can finally create the creator:
549+
if (creatorProps != null) {
550+
_propertyBasedCreator = PropertyBasedCreator.construct(ctxt, _valueInstantiator, creatorProps);
551+
}
552+
526553
if (extTypes != null) {
527554
_externalTypeIdHandler = extTypes.build();
528555
// we consider this non-standard, to offline handling

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -534,13 +534,13 @@ protected void addBeanProps(DeserializationContext ctxt,
534534
+name+"' (in class "+beanDesc.getBeanClass().getName()+")");
535535
}
536536
if (prop != null) {
537-
cprop = cprop.withFallbackSetter(prop);
537+
cprop.setFallbackSetter(prop);
538538
}
539539
prop = cprop;
540540
builder.addCreatorProperty(cprop);
541541
continue;
542542
}
543-
543+
544544
if (prop != null) {
545545
Class<?>[] views = propDef.findViews();
546546
if (views == null) {

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

+14-17
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import com.fasterxml.jackson.core.JsonParser;
77
import com.fasterxml.jackson.core.JsonProcessingException;
8-
import com.fasterxml.jackson.databind.DeserializationContext;
98
import com.fasterxml.jackson.databind.*;
109
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
1110
import com.fasterxml.jackson.databind.introspect.AnnotatedParameter;
@@ -50,11 +49,14 @@ public class CreatorProperty
5049
* In special cases, when implementing "updateValue", we can not use
5150
* constructors or factory methods, but have to fall back on using a
5251
* setter (or mutable field property). If so, this refers to that fallback
53-
* accessor
52+
* accessor.
53+
*<p>
54+
* Mutable only to allow setting after construction, but must be strictly
55+
* set before any use.
5456
*
5557
* @since 2.3
5658
*/
57-
protected final SettableBeanProperty _fallbackSetter;
59+
protected SettableBeanProperty _fallbackSetter;
5860

5961
/**
6062
* @param name Name of the logical property
@@ -102,17 +104,6 @@ protected CreatorProperty(CreatorProperty src, JsonDeserializer<?> deser) {
102104
_fallbackSetter = src._fallbackSetter;
103105
}
104106

105-
/**
106-
* @since 2.3
107-
*/
108-
protected CreatorProperty(CreatorProperty src, SettableBeanProperty fallbackSetter) {
109-
super(src);
110-
_annotated = src._annotated;
111-
_creatorIndex = src._creatorIndex;
112-
_injectableValueId = src._injectableValueId;
113-
_fallbackSetter = fallbackSetter;
114-
}
115-
116107
@Override
117108
public CreatorProperty withName(PropertyName newName) {
118109
return new CreatorProperty(this, newName);
@@ -123,10 +114,16 @@ public CreatorProperty withValueDeserializer(JsonDeserializer<?> deser) {
123114
return new CreatorProperty(this, deser);
124115
}
125116

126-
public CreatorProperty withFallbackSetter(SettableBeanProperty fallbackSetter) {
127-
return new CreatorProperty(this, fallbackSetter);
117+
/**
118+
* NOTE: one exception to immutability, due to problems with CreatorProperty instances
119+
* being shared between Bean, separate PropertyBasedCreator
120+
*
121+
* @since 2.6.0
122+
*/
123+
public void setFallbackSetter(SettableBeanProperty fallbackSetter) {
124+
_fallbackSetter = fallbackSetter;
128125
}
129-
126+
130127
/**
131128
* Method that can be called to locate value to be injected for this
132129
* property, if it is configured for this.

src/test/java/com/fasterxml/jackson/failing/ConvertingAbstractSerializer795Test.java renamed to src/test/java/com/fasterxml/jackson/databind/convert/ConvertingAbstractSerializer795Test.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.fasterxml.jackson.failing;
1+
package com.fasterxml.jackson.databind.convert;
22

33
import com.fasterxml.jackson.annotation.*;
44
import com.fasterxml.jackson.databind.*;
@@ -47,7 +47,6 @@ public NonAbstractCustomType(String v) {
4747
}
4848
}
4949

50-
5150
public static class NonAbstractCustomTypeDeserializationConverter extends StdConverter<String, NonAbstractCustomType>{
5251

5352
@Override
@@ -56,7 +55,6 @@ public NonAbstractCustomType convert(String arg) {
5655
}
5756
}
5857

59-
6058
public static class NonAbstractCustomTypeUser {
6159
@JsonProperty
6260
@JsonDeserialize(converter = NonAbstractCustomTypeDeserializationConverter.class)

0 commit comments

Comments
 (0)