Skip to content

Commit c612c1e

Browse files
committed
Fix #1382
1 parent 5939b1a commit c612c1e

File tree

6 files changed

+74
-11
lines changed

6 files changed

+74
-11
lines changed

release-notes/VERSION-2.x

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ Project: jackson-databind
55

66
2.9.4 (not yet released)
77

8+
#1382: `@JsonProperty(access=READ_ONLY)` unxepected behaviour with `Collections`
9+
(reported by hexfaker@github)
810
#1673: Serialising generic value classes via Reference Types (like Optional) fails
911
to include type information
1012
(reported by Pier-Luc W)

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

+7
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,13 @@ public JsonPOJOBuilder.Value getBuilderConfig() {
327327
return _builderConfig;
328328
}
329329

330+
/**
331+
* @since 2.9.4
332+
*/
333+
public boolean hasIgnorable(String name) {
334+
return (_ignorableProps != null) && _ignorableProps.contains(name);
335+
}
336+
330337
/*
331338
/**********************************************************
332339
/* Build method(s)

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

+12-5
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,8 @@ protected void addBeanProps(DeserializationContext ctxt,
482482
if (anySetter != null) {
483483
builder.setAnySetter(constructAnySetter(ctxt, beanDesc, anySetter));
484484
} else {
485+
// 23-Jan-2018, tatu: although [databind#1805] would suggest we should block
486+
// properties regardless, for now only consider unless there's any setter...
485487
Collection<String> ignored2 = beanDesc.getIgnoredPropertyNames();
486488
if (ignored2 != null) {
487489
for (String propName : ignored2) {
@@ -509,10 +511,9 @@ protected void addBeanProps(DeserializationContext ctxt,
509511
for (BeanPropertyDefinition propDef : propDefs) {
510512
SettableBeanProperty prop = null;
511513

512-
/* 18-Oct-2013, tatu: Although constructor parameters have highest precedence,
513-
* we need to do linkage (as per [databind#318]), and so need to start with
514-
* other types, and only then create constructor parameter, if any.
515-
*/
514+
// 18-Oct-2013, tatu: Although constructor parameters have highest precedence,
515+
// we need to do linkage (as per [databind#318]), and so need to start with
516+
// other types, and only then create constructor parameter, if any.
516517
if (propDef.hasSetter()) {
517518
AnnotatedMethod setter = propDef.getSetter();
518519
JavaType propertyType = setter.getParameterType(0);
@@ -526,7 +527,13 @@ protected void addBeanProps(DeserializationContext ctxt,
526527
AnnotatedMethod getter = propDef.getGetter();
527528
if (getter != null) {
528529
if (useGettersAsSetters && _isSetterlessType(getter.getRawType())) {
529-
prop = constructSetterlessProperty(ctxt, beanDesc, propDef);
530+
// 23-Jan-2018, tatu: As per [databind#1805], need to ensure we don't
531+
// accidentally sneak in getter-as-setter for `READ_ONLY` properties
532+
if (builder.hasIgnorable(propDef.getName())) {
533+
;
534+
} else {
535+
prop = constructSetterlessProperty(ctxt, beanDesc, propDef);
536+
}
530537
} else if (!propDef.hasConstructorParameter()) {
531538
PropertyMetadata md = propDef.getMetadata();
532539
// 25-Oct-2016, tatu: If merging enabled, might not need setter.

src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,7 @@ protected void _removeUnwantedProperties(Map<String, POJOPropertyBuilder> props)
721721
}
722722
// otherwise just remove ones marked to be ignored
723723
prop.removeIgnored();
724-
if (!_forSerialization && !prop.couldDeserialize()) {
724+
if (!prop.couldDeserialize()) {
725725
_collectIgnorals(prop.getName());
726726
}
727727
}
@@ -742,7 +742,7 @@ protected void _removeUnwantedAccessor(Map<String, POJOPropertyBuilder> props)
742742
POJOPropertyBuilder prop = it.next();
743743
// 26-Jan-2017, tatu: [databind#935]: need to denote removal of
744744
JsonProperty.Access acc = prop.removeNonVisible(inferMutators);
745-
if (!_forSerialization && (acc == JsonProperty.Access.READ_ONLY)) {
745+
if (acc == JsonProperty.Access.READ_ONLY) {
746746
_collectIgnorals(prop.getName());
747747
}
748748
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ public void testGenericAnySetter() throws Exception
367367
assertEquals(integerGeneric.getDynamicallyMappedProperties(), integerGenericMap);
368368
}
369369

370-
/*
370+
/*
371371
/**********************************************************
372372
/* Private helper methods
373373
/**********************************************************

src/test/java/com/fasterxml/jackson/failing/ReadOnlyDeser1382Test.java

+50-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.*;
44

5+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
56
import com.fasterxml.jackson.annotation.JsonProperty;
67
import com.fasterxml.jackson.databind.*;
78

@@ -21,11 +22,57 @@ public Foo setList(List<Long> list) {
2122
}
2223
}
2324

24-
public void testReadOnly() throws Exception
25+
// [databind#1805]
26+
static class UserWithReadOnly {
27+
public String name;
28+
29+
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
30+
public List<String> getRoles() {
31+
return Arrays.asList("admin", "monitor");
32+
}
33+
}
34+
35+
// [databind#1805]
36+
@JsonIgnoreProperties(value={ "roles" }, allowGetters=true)
37+
static class UserAllowGetters {
38+
public String name;
39+
40+
public List<String> getRoles() {
41+
return Arrays.asList("admin", "monitor");
42+
}
43+
}
44+
45+
/*
46+
/**********************************************************
47+
/* Test methods
48+
/**********************************************************
49+
*/
50+
51+
private final ObjectMapper MAPPER = newObjectMapper();
52+
53+
public void testReadOnly1382() throws Exception
2554
{
26-
final ObjectMapper mapper = new ObjectMapper();
2755
String payload = "{\"list\":[1,2,3,4]}";
28-
Foo foo = mapper.readValue(payload, Foo.class);
56+
Foo foo = MAPPER.readValue(payload, Foo.class);
2957
assertTrue("List should be empty", foo.getList().isEmpty());
3058
}
59+
60+
// [databind#1805]
61+
public void testViaReadOnly() throws Exception {
62+
UserWithReadOnly user = new UserWithReadOnly();
63+
user.name = "foo";
64+
String json = MAPPER.writeValueAsString(user);
65+
UserWithReadOnly result = MAPPER.readValue(json, UserWithReadOnly.class);
66+
assertNotNull(result);
67+
}
68+
69+
// [databind#1805]
70+
public void testUsingAllowGetters() throws Exception {
71+
UserAllowGetters user = new UserAllowGetters();
72+
user.name = "foo";
73+
String json = MAPPER.writeValueAsString(user);
74+
assertTrue(json.contains("roles"));
75+
UserAllowGetters result = MAPPER.readValue(json, UserAllowGetters.class);
76+
assertNotNull(result);
77+
}
3178
}

0 commit comments

Comments
 (0)