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

Add configureAbsentsAsNulls config setting #11

Merged
merged 1 commit into from
Jun 5, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.fasterxml.jackson.datatype.jdk8;

import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;

import java.util.List;
import java.util.Optional;

/**
* {@link BeanSerializerModifier} needed to sneak in handler to exclude "absent"
* optional values iff handling of "absent as nulls" is enabled.
*/
public class Jdk8BeanSerializerModifier extends BeanSerializerModifier
{
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
BeanDescription beanDesc,
List<BeanPropertyWriter> beanProperties)
{
for (int i = 0; i < beanProperties.size(); ++i) {
final BeanPropertyWriter writer = beanProperties.get(i);
if (Optional.class.isAssignableFrom(writer.getPropertyType())) {
beanProperties.set(i, new Jdk8OptionalBeanPropertyWriter(writer));
}
}
return beanProperties;
}
}
38 changes: 38 additions & 0 deletions src/main/java/com/fasterxml/jackson/datatype/jdk8/Jdk8Module.java
Original file line number Diff line number Diff line change
@@ -5,19 +5,57 @@

public class Jdk8Module extends Module
{
/**
* Configuration setting that determines whether `Optional.empty()` is
* considered "same as null" for serialization purposes; that is, to be
* filtered same as nulls are.
* If enabled, absent values are treated like nulls; if disabled, they are not.
* In either case, absent values are always considered "empty".
*<p>
* Default value is `false` for backwards compatibility (2.5 and prior
* only had this behavior).
*<p>
* Note that this setting MUST be changed BEFORE registering the module:
* changes after registration will have no effect.
*/
protected boolean _cfgHandleAbsentAsNull = false;

@Override
public void setupModule(SetupContext context) {
context.addSerializers(new Jdk8Serializers());
context.addDeserializers(new Jdk8Deserializers());
// And to fully support Optionals, need to modify type info:
context.addTypeModifier(new Jdk8TypeModifier());

// Allow enabling "treat Optional.empty() like Java nulls"
if (_cfgHandleAbsentAsNull) {
context.addBeanSerializerModifier(new Jdk8BeanSerializerModifier());
}
}

@Override
public Version version() {
return PackageVersion.VERSION;
}

/**
* Configuration method that may be used to change configuration setting
* {@link #_cfgHandleAbsentAsNull}: enabling means that `Optional.empty()` values
* are handled like Java nulls (wrt filtering on serialization); disabling that
* they are only treated as "empty" values, but not like native Java nulls.
* Recommended setting for this value is `false`. For compatibility with older versions
* of other "optional" values (like Guava optionals), it can be set to 'true'. The
* default is `false` for backwards compatibility.
*
* @return This module instance, useful for chaining calls
*
* @since 2.6
*/
public Jdk8Module configureAbsentsAsNulls(boolean state) {
_cfgHandleAbsentAsNull = state;
return this;
}

@Override
public int hashCode() {
return getClass().hashCode();
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.fasterxml.jackson.datatype.jdk8;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;

import java.util.Optional;

public class Jdk8OptionalBeanPropertyWriter extends BeanPropertyWriter {

protected Jdk8OptionalBeanPropertyWriter(BeanPropertyWriter base) {
super(base);
}

@Override
public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov) throws Exception
{
if (_nullSerializer == null) {
Object value = get(bean);
if (value == null || Optional.empty().equals(value)) {
return;
}
}
super.serializeAsField(bean, jgen, prov);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.fasterxml.jackson.datatype.jdk8;

import java.util.Optional;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;

public class TestConfigureAbsentsAsNulls extends ModuleTestBase
{
@JsonAutoDetect(fieldVisibility=Visibility.ANY)
public static final class OptionalData {
public Optional<String> myString = Optional.empty();
}

/*
/**********************************************************************
/* Test methods
/**********************************************************************
*/

public void testConfigAbsentsAsNullsTrue() throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module().configureAbsentsAsNulls(true));

OptionalData data = new OptionalData();
String value = mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL).writeValueAsString(data);
assertEquals("{}", value);
}

public void testConfigAbsentsAsNullsFalse() throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module().configureAbsentsAsNulls(false));

OptionalData data = new OptionalData();
String value = mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL).writeValueAsString(data);
assertEquals("{\"myString\":null}", value);
}

public void testConfigNonAbsentAbsentsAsNullsTrue() throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module().configureAbsentsAsNulls(true));

OptionalData data = new OptionalData();
String value = mapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT).writeValueAsString(data);
assertEquals("{}", value);
}

public void testConfigNonAbsentAbsentsAsNullsFalse() throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module().configureAbsentsAsNulls(false));

OptionalData data = new OptionalData();
String value = mapper.setSerializationInclusion(JsonInclude.Include.NON_ABSENT).writeValueAsString(data);
assertEquals("{}", value);
}
}