Skip to content

Commit 8098ff3

Browse files
deblocktcowtowncoder
authored andcommitted
Remove usage of _neitherNull on findProperty (#1918)
* Fix #1912 Remove usage of _neitherNull on findProperty to get custom property if possible. * [#1912] add unit test
1 parent ff83469 commit 8098ff3

File tree

2 files changed

+106
-15
lines changed

2 files changed

+106
-15
lines changed

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ protected BeanDeserializerBase(BeanDeserializerBase src, boolean ignoreAllUnknow
261261

262262
_vanillaProcessing = src._vanillaProcessing;
263263
}
264-
264+
265265
protected BeanDeserializerBase(BeanDeserializerBase src, NameTransformer unwrapper)
266266
{
267267
super(src._beanType);
@@ -415,7 +415,7 @@ public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) {
415415
* Fluent factory for creating a variant that can handle
416416
* POJO output as a JSON Array. Implementations may ignore this request
417417
* if no such input is possible.
418-
*
418+
*
419419
* @since 2.1
420420
*/
421421
protected abstract BeanDeserializerBase asArrayDeserializer();
@@ -644,7 +644,7 @@ private JsonDeserializer<Object> _findDelegateDeserializer(DeserializationContex
644644
*<p>
645645
* NOTE: returned deserializer is NOT yet contextualized, caller needs to take
646646
* care to do that.
647-
*
647+
*
648648
* @since 2.2
649649
*/
650650
protected JsonDeserializer<Object> findConvertingDeserializer(DeserializationContext ctxt,
@@ -665,7 +665,7 @@ protected JsonDeserializer<Object> findConvertingDeserializer(DeserializationCon
665665
}
666666
return null;
667667
}
668-
668+
669669
/**
670670
* Although most of post-processing is done in resolve(), we only get
671671
* access to referring property's annotations here; and this is needed
@@ -1026,7 +1026,7 @@ public Iterator<SettableBeanProperty> properties()
10261026
* Accessor for finding properties that represents values to pass
10271027
* through property-based creator method (constructor or
10281028
* factory method)
1029-
*
1029+
*
10301030
* @since 2.0
10311031
*/
10321032
public Iterator<SettableBeanProperty> creatorProperties()
@@ -1047,14 +1047,14 @@ public SettableBeanProperty findProperty(PropertyName propertyName)
10471047
* Accessor for finding the property with given name, if POJO
10481048
* has one. Name used is the external name, i.e. name used
10491049
* in external data representation (JSON).
1050-
*
1050+
*
10511051
* @since 2.0
10521052
*/
10531053
public SettableBeanProperty findProperty(String propertyName)
10541054
{
10551055
SettableBeanProperty prop = (_beanProperties == null) ?
10561056
null : _beanProperties.find(propertyName);
1057-
if (_neitherNull(prop, _propertyBasedCreator)) {
1057+
if (prop == null && _propertyBasedCreator != null) {
10581058
prop = _propertyBasedCreator.findCreatorProperty(propertyName);
10591059
}
10601060
return prop;
@@ -1067,14 +1067,14 @@ public SettableBeanProperty findProperty(String propertyName)
10671067
* since properties are not directly indexable; however, for most
10681068
* instances difference is not significant as number of properties
10691069
* is low.
1070-
*
1070+
*
10711071
* @since 2.3
10721072
*/
10731073
public SettableBeanProperty findProperty(int propertyIndex)
10741074
{
10751075
SettableBeanProperty prop = (_beanProperties == null) ?
10761076
null : _beanProperties.find(propertyIndex);
1077-
if (_neitherNull(prop, _propertyBasedCreator)) {
1077+
if (prop == null && _propertyBasedCreator != null) {
10781078
prop = _propertyBasedCreator.findCreatorProperty(propertyIndex);
10791079
}
10801080
return prop;
@@ -1113,7 +1113,7 @@ public ValueInstantiator getValueInstantiator() {
11131113
*
11141114
* @param original Property to replace
11151115
* @param replacement Property to replace it with
1116-
*
1116+
*
11171117
* @since 2.1
11181118
*/
11191119
public void replaceProperty(SettableBeanProperty original,
@@ -1585,7 +1585,7 @@ protected void handleUnknownProperty(JsonParser p, DeserializationContext ctxt,
15851585
/**
15861586
* Method called when an explicitly ignored property (one specified with a
15871587
* name to match, either by property annotation or class annotation) is encountered.
1588-
*
1588+
*
15891589
* @since 2.3
15901590
*/
15911591
protected void handleIgnoredProperty(JsonParser p, DeserializationContext ctxt,

src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java

Lines changed: 95 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
import java.io.IOException;
44
import java.util.*;
55

6+
import com.fasterxml.jackson.annotation.JsonCreator;
7+
import com.fasterxml.jackson.annotation.JsonProperty;
68
import com.fasterxml.jackson.core.*;
79
import com.fasterxml.jackson.databind.*;
8-
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
9-
import com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder;
10-
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
1110
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
1211
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;
1312
import com.fasterxml.jackson.databind.module.SimpleModule;
@@ -139,7 +138,92 @@ public void setupModule(SetupContext context) {
139138
context.addBeanDeserializerModifier(new Issue476DeserializerModifier());
140139
}
141140
}
142-
141+
142+
public static class Issue1912Bean {
143+
public Issue1912SubBean subBean;
144+
145+
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES) // This is need to populate _propertyBasedCreator on BeanDeserializerBase
146+
public Issue1912Bean(@JsonProperty("subBean") Issue1912SubBean subBean) {
147+
this.subBean = subBean;
148+
}
149+
}
150+
public static class Issue1912SubBean {
151+
public String a;
152+
153+
public Issue1912SubBean() { }
154+
155+
public Issue1912SubBean(String a) {
156+
this.a = a;
157+
}
158+
}
159+
160+
public static class Issue1912CustomBeanDeserializer extends JsonDeserializer<Issue1912Bean> {
161+
private BeanDeserializer defaultDeserializer;
162+
163+
public Issue1912CustomBeanDeserializer(BeanDeserializer defaultDeserializer) {
164+
this.defaultDeserializer = defaultDeserializer;
165+
}
166+
167+
@Override
168+
public Issue1912Bean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
169+
// this is need on some cases, this populate _propertyBasedCreator
170+
defaultDeserializer.resolve(ctxt);
171+
172+
p.nextFieldName(); // read subBean
173+
p.nextToken(); // read start object
174+
175+
Issue1912SubBean subBean = (Issue1912SubBean) defaultDeserializer.findProperty("subBean").deserialize(p, ctxt);
176+
177+
return new Issue1912Bean(subBean);
178+
}
179+
}
180+
181+
public static class Issue1912CustomPropertyDeserializer extends JsonDeserializer<Issue1912SubBean> {
182+
183+
@Override
184+
public Issue1912SubBean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
185+
p.nextFieldName(); // read "a"
186+
Issue1912SubBean object = new Issue1912SubBean(p.nextTextValue() + "_custom");
187+
p.nextToken();
188+
return object;
189+
}
190+
}
191+
public static class Issue1912UseAddOrReplacePropertyDeserializerModifier extends BeanDeserializerModifier {
192+
193+
@Override
194+
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
195+
if (beanDesc.getBeanClass() == Issue1912Bean.class) {
196+
return new Issue1912CustomBeanDeserializer((BeanDeserializer) deserializer);
197+
}
198+
return super.modifyDeserializer(config, beanDesc, deserializer);
199+
}
200+
201+
@Override
202+
public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BeanDescription beanDesc, BeanDeserializerBuilder builder) {
203+
if (beanDesc.getBeanClass() == Issue1912Bean.class) {
204+
Iterator<SettableBeanProperty> props = builder.getProperties();
205+
while (props.hasNext()) {
206+
SettableBeanProperty prop = props.next();
207+
SettableBeanProperty propWithCustomDeserializer = prop.withValueDeserializer(new Issue1912CustomPropertyDeserializer());
208+
builder.addOrReplaceProperty(propWithCustomDeserializer, true);
209+
}
210+
}
211+
212+
return builder;
213+
}
214+
}
215+
public class Issue1912Module extends SimpleModule {
216+
217+
public Issue1912Module() {
218+
super("Issue1912Module", Version.unknownVersion());
219+
}
220+
221+
@Override
222+
public void setupModule(SetupContext context) {
223+
context.addBeanDeserializerModifier(new Issue1912UseAddOrReplacePropertyDeserializerModifier());
224+
}
225+
}
226+
143227
// [Issue#121], arrays, collections, maps
144228

145229
enum EnumABC { A, B, C; }
@@ -380,4 +464,11 @@ public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
380464
assertEquals("ABCDEF", result);
381465
}
382466

467+
public void testAddOrReplacePropertyIsUsedOnDeserialization() throws Exception {
468+
ObjectMapper mapper = new ObjectMapper();
469+
mapper.registerModule(new Issue1912Module());
470+
471+
Issue1912Bean result = mapper.readValue("{\"subBean\": {\"a\":\"foo\"}}", Issue1912Bean.class);
472+
assertEquals("foo_custom", result.subBean.a);
473+
}
383474
}

0 commit comments

Comments
 (0)