Skip to content
This repository was archived by the owner on Nov 7, 2019. It is now read-only.

Commit 39a8892

Browse files
committed
Merge pull request #11 from hgschmie/master
Add configureAbsentsAsNulls config setting
2 parents 7c54a99 + a4a0fb4 commit 39a8892

File tree

4 files changed

+153
-0
lines changed

4 files changed

+153
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.fasterxml.jackson.datatype.jdk8;
2+
3+
import com.fasterxml.jackson.databind.BeanDescription;
4+
import com.fasterxml.jackson.databind.SerializationConfig;
5+
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
6+
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
7+
8+
import java.util.List;
9+
import java.util.Optional;
10+
11+
/**
12+
* {@link BeanSerializerModifier} needed to sneak in handler to exclude "absent"
13+
* optional values iff handling of "absent as nulls" is enabled.
14+
*/
15+
public class Jdk8BeanSerializerModifier extends BeanSerializerModifier
16+
{
17+
@Override
18+
public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
19+
BeanDescription beanDesc,
20+
List<BeanPropertyWriter> beanProperties)
21+
{
22+
for (int i = 0; i < beanProperties.size(); ++i) {
23+
final BeanPropertyWriter writer = beanProperties.get(i);
24+
if (Optional.class.isAssignableFrom(writer.getPropertyType())) {
25+
beanProperties.set(i, new Jdk8OptionalBeanPropertyWriter(writer));
26+
}
27+
}
28+
return beanProperties;
29+
}
30+
}

src/main/java/com/fasterxml/jackson/datatype/jdk8/Jdk8Module.java

+38
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,57 @@
55

66
public class Jdk8Module extends Module
77
{
8+
/**
9+
* Configuration setting that determines whether `Optional.empty()` is
10+
* considered "same as null" for serialization purposes; that is, to be
11+
* filtered same as nulls are.
12+
* If enabled, absent values are treated like nulls; if disabled, they are not.
13+
* In either case, absent values are always considered "empty".
14+
*<p>
15+
* Default value is `false` for backwards compatibility (2.5 and prior
16+
* only had this behavior).
17+
*<p>
18+
* Note that this setting MUST be changed BEFORE registering the module:
19+
* changes after registration will have no effect.
20+
*/
21+
protected boolean _cfgHandleAbsentAsNull = false;
22+
823
@Override
924
public void setupModule(SetupContext context) {
1025
context.addSerializers(new Jdk8Serializers());
1126
context.addDeserializers(new Jdk8Deserializers());
1227
// And to fully support Optionals, need to modify type info:
1328
context.addTypeModifier(new Jdk8TypeModifier());
29+
30+
// Allow enabling "treat Optional.empty() like Java nulls"
31+
if (_cfgHandleAbsentAsNull) {
32+
context.addBeanSerializerModifier(new Jdk8BeanSerializerModifier());
33+
}
1434
}
1535

1636
@Override
1737
public Version version() {
1838
return PackageVersion.VERSION;
1939
}
2040

41+
/**
42+
* Configuration method that may be used to change configuration setting
43+
* {@link #_cfgHandleAbsentAsNull}: enabling means that `Optional.empty()` values
44+
* are handled like Java nulls (wrt filtering on serialization); disabling that
45+
* they are only treated as "empty" values, but not like native Java nulls.
46+
* Recommended setting for this value is `false`. For compatibility with older versions
47+
* of other "optional" values (like Guava optionals), it can be set to 'true'. The
48+
* default is `false` for backwards compatibility.
49+
*
50+
* @return This module instance, useful for chaining calls
51+
*
52+
* @since 2.6
53+
*/
54+
public Jdk8Module configureAbsentsAsNulls(boolean state) {
55+
_cfgHandleAbsentAsNull = state;
56+
return this;
57+
}
58+
2159
@Override
2260
public int hashCode() {
2361
return getClass().hashCode();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.fasterxml.jackson.datatype.jdk8;
2+
3+
import com.fasterxml.jackson.core.JsonGenerator;
4+
import com.fasterxml.jackson.databind.SerializerProvider;
5+
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
6+
7+
import java.util.Optional;
8+
9+
public class Jdk8OptionalBeanPropertyWriter extends BeanPropertyWriter {
10+
11+
protected Jdk8OptionalBeanPropertyWriter(BeanPropertyWriter base) {
12+
super(base);
13+
}
14+
15+
@Override
16+
public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov) throws Exception
17+
{
18+
if (_nullSerializer == null) {
19+
Object value = get(bean);
20+
if (value == null || Optional.empty().equals(value)) {
21+
return;
22+
}
23+
}
24+
super.serializeAsField(bean, jgen, prov);
25+
}
26+
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.fasterxml.jackson.datatype.jdk8;
2+
3+
import java.util.Optional;
4+
5+
import com.fasterxml.jackson.annotation.JsonAutoDetect;
6+
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
7+
import com.fasterxml.jackson.annotation.JsonInclude;
8+
import com.fasterxml.jackson.databind.ObjectMapper;
9+
10+
public class TestConfigureAbsentsAsNulls extends ModuleTestBase
11+
{
12+
@JsonAutoDetect(fieldVisibility=Visibility.ANY)
13+
public static final class OptionalData {
14+
public Optional<String> myString = Optional.empty();
15+
}
16+
17+
/*
18+
/**********************************************************************
19+
/* Test methods
20+
/**********************************************************************
21+
*/
22+
23+
public void testConfigAbsentsAsNullsTrue() throws Exception {
24+
ObjectMapper mapper = new ObjectMapper();
25+
mapper.registerModule(new Jdk8Module().configureAbsentsAsNulls(true));
26+
27+
OptionalData data = new OptionalData();
28+
String value = mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL).writeValueAsString(data);
29+
assertEquals("{}", value);
30+
}
31+
32+
public void testConfigAbsentsAsNullsFalse() throws Exception {
33+
ObjectMapper mapper = new ObjectMapper();
34+
mapper.registerModule(new Jdk8Module().configureAbsentsAsNulls(false));
35+
36+
OptionalData data = new OptionalData();
37+
String value = mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL).writeValueAsString(data);
38+
assertEquals("{\"myString\":null}", value);
39+
}
40+
41+
public void testConfigNonAbsentAbsentsAsNullsTrue() throws Exception {
42+
ObjectMapper mapper = new ObjectMapper();
43+
mapper.registerModule(new Jdk8Module().configureAbsentsAsNulls(true));
44+
45+
OptionalData data = new OptionalData();
46+
String value = mapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT).writeValueAsString(data);
47+
assertEquals("{}", value);
48+
}
49+
50+
public void testConfigNonAbsentAbsentsAsNullsFalse() throws Exception {
51+
ObjectMapper mapper = new ObjectMapper();
52+
mapper.registerModule(new Jdk8Module().configureAbsentsAsNulls(false));
53+
54+
OptionalData data = new OptionalData();
55+
String value = mapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT).writeValueAsString(data);
56+
assertEquals("{}", value);
57+
}
58+
}

0 commit comments

Comments
 (0)