Skip to content

Commit f0ef5cd

Browse files
committed
fix #2675
1 parent acd2e38 commit f0ef5cd

File tree

7 files changed

+88
-30
lines changed

7 files changed

+88
-30
lines changed

release-notes/VERSION-2.x

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Project: jackson-databind
1313
(reported by Incara@github)
1414
#2091: `ReferenceType` does not expose valid containedType
1515
(reported by Nate B)
16+
#2675: Support use of `Void` valued properties (`MapperFeature.ALLOW_VOID_VALUED_PROPERTIES`)
1617
#2683: Explicitly fail (de)serialization of `java.time.*` types in absence of
1718
registered custom (de)serializers
1819
#2707: Improve description included in by `DeserializationContext.handleUnexpectedToken()`

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

+13
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,19 @@ public enum MapperFeature implements ConfigFeature
213213
*/
214214
INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES(true),
215215

216+
/**
217+
* Feature that determines whether nominal property type of {@link Void} is
218+
* allowed for Getter methods to indicate {@code null} valued pseudo-property
219+
* or not. If enabled, such properties are recognized (see [databind#2675] for
220+
* reasons -- mostly things related to frameworks, code generation); if disabled,
221+
* such property accessors (or at least getters) are ignored.
222+
*<p>
223+
* Feature is disabled by default (in 2.12) for backwards compatibility.
224+
*
225+
* @since 2.12
226+
*/
227+
ALLOW_VOID_VALUED_PROPERTIES(false),
228+
216229
/*
217230
/******************************************************
218231
/* Access modifier handling

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,14 @@ public Class<?> getRawReturnType() {
215215
* false, otherwise true
216216
*
217217
* @since 2.4
218+
*
219+
* @deprecated Since 2.12 (related to [databind#2675]), needs to be configurable
218220
*/
221+
@Deprecated
219222
public boolean hasReturnType() {
220223
Class<?> rt = getRawReturnType();
221-
return (rt != Void.TYPE && rt != Void.class);
224+
// also, as per [databind#2675], only consider `void` to be real "No return type"
225+
return (rt != Void.TYPE);
222226
}
223227

224228
/*

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

+8-3
Original file line numberDiff line numberDiff line change
@@ -580,10 +580,15 @@ protected void _addGetterMethod(Map<String, POJOPropertyBuilder> props,
580580
AnnotatedMethod m, AnnotationIntrospector ai)
581581
{
582582
// Very first thing: skip if not returning any value
583-
if (!m.hasReturnType()) {
584-
return;
583+
// 06-May-2020, tatu: [databind#2675] changes handling slightly...
584+
{
585+
final Class<?> rt = m.getRawReturnType();
586+
if ((rt == Void.TYPE) ||
587+
((rt == Void.class) && !_config.isEnabled(MapperFeature.ALLOW_VOID_VALUED_PROPERTIES))) {
588+
return;
589+
}
585590
}
586-
591+
587592
// any getter?
588593
// @JsonAnyGetter?
589594
if (Boolean.TRUE.equals(ai.hasAnyGetter(m))) {

src/main/java/com/fasterxml/jackson/databind/ser/BeanSerializerFactory.java

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
import com.fasterxml.jackson.databind.*;
1111
import com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig;
12-
import com.fasterxml.jackson.databind.deser.impl.UnsupportedTypeDeserializer;
1312
import com.fasterxml.jackson.databind.introspect.*;
1413
import com.fasterxml.jackson.databind.jsontype.NamedType;
1514
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.fasterxml.jackson.databind.deser.jdk;
2+
3+
import com.fasterxml.jackson.databind.*;
4+
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
5+
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
6+
7+
// [databind#2675]: Void-valued "properties"
8+
public class VoidProperties2675Test extends BaseMapTest
9+
{
10+
static class VoidBean {
11+
protected Void value;
12+
13+
public Void getValue() { return null; }
14+
15+
// public void setValue(Void v) { }
16+
}
17+
18+
/*
19+
/**********************************************************************
20+
/* Test methods
21+
/**********************************************************************
22+
*/
23+
24+
private final ObjectMapper DEFAULT_MAPPER = sharedMapper();
25+
26+
private final ObjectMapper VOID_MAPPER = jsonMapperBuilder()
27+
.enable(MapperFeature.ALLOW_VOID_VALUED_PROPERTIES)
28+
.build();
29+
30+
public void testVoidBeanSerialization() throws Exception
31+
{
32+
// By default (2.x), not enabled:
33+
try {
34+
DEFAULT_MAPPER.writeValueAsString(new VoidBean());
35+
fail("Should not pass");
36+
} catch (InvalidDefinitionException e) {
37+
verifyException(e, "no properties discovered");
38+
}
39+
40+
// but when enabled
41+
assertEquals("{\"value\":null}", VOID_MAPPER.writeValueAsString(new VoidBean()));
42+
}
43+
44+
public void testVoidBeanDeserialization() throws Exception {
45+
final String DOC = "{\"value\":null}";
46+
VoidBean result;
47+
48+
// By default (2.x), not enabled:
49+
try {
50+
result = DEFAULT_MAPPER.readValue(DOC, VoidBean.class);
51+
fail("Should not pass");
52+
} catch (UnrecognizedPropertyException e) {
53+
verifyException(e, "Unrecognized field \"value\"");
54+
}
55+
56+
// but when enabled
57+
result = VOID_MAPPER.readValue(DOC, VoidBean.class);
58+
assertNotNull(result);
59+
assertNull(result.getValue());
60+
}
61+
}

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

-25
This file was deleted.

0 commit comments

Comments
 (0)