diff --git a/afterburner/src/main/java/com/fasterxml/jackson/module/afterburner/ser/StringFieldPropertyWriter.java b/afterburner/src/main/java/com/fasterxml/jackson/module/afterburner/ser/StringFieldPropertyWriter.java index 326a7eaa..fcb6a12b 100644 --- a/afterburner/src/main/java/com/fasterxml/jackson/module/afterburner/ser/StringFieldPropertyWriter.java +++ b/afterburner/src/main/java/com/fasterxml/jackson/module/afterburner/ser/StringFieldPropertyWriter.java @@ -48,7 +48,10 @@ public final void serializeAsField(Object bean, JsonGenerator gen, SerializerPro } // Null (etc) handling; copied from super-class impl if (value == null) { - if (!_suppressNulls) { + if (_nullSerializer != null) { + gen.writeFieldName(_fastName); + _nullSerializer.serialize(null, gen, prov); + } else if (!_suppressNulls) { gen.writeFieldName(_fastName); prov.defaultSerializeNull(gen); } diff --git a/afterburner/src/main/java/com/fasterxml/jackson/module/afterburner/ser/StringMethodPropertyWriter.java b/afterburner/src/main/java/com/fasterxml/jackson/module/afterburner/ser/StringMethodPropertyWriter.java index 16c1ca34..7e6bdf95 100644 --- a/afterburner/src/main/java/com/fasterxml/jackson/module/afterburner/ser/StringMethodPropertyWriter.java +++ b/afterburner/src/main/java/com/fasterxml/jackson/module/afterburner/ser/StringMethodPropertyWriter.java @@ -48,7 +48,10 @@ public final void serializeAsField(Object bean, JsonGenerator gen, SerializerPro } // Null (etc) handling; copied from super-class impl if (value == null) { - if (!_suppressNulls) { + if (_nullSerializer != null) { + gen.writeFieldName(_fastName); + _nullSerializer.serialize(null, gen, prov); + } else if (!_suppressNulls) { gen.writeFieldName(_fastName); prov.defaultSerializeNull(gen); } diff --git a/afterburner/src/test/java/com/fasterxml/jackson/module/afterburner/ser/NullSerializationTest.java b/afterburner/src/test/java/com/fasterxml/jackson/module/afterburner/ser/NullSerializationTest.java new file mode 100644 index 00000000..fb8afd04 --- /dev/null +++ b/afterburner/src/test/java/com/fasterxml/jackson/module/afterburner/ser/NullSerializationTest.java @@ -0,0 +1,121 @@ +package com.fasterxml.jackson.module.afterburner.ser; + +import java.io.*; + +import com.fasterxml.jackson.core.*; + +import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider; +import com.fasterxml.jackson.databind.ser.SerializerFactory; +import com.fasterxml.jackson.module.afterburner.AfterburnerTestBase; + +// Copied from [com.fasterxml.jackson.databind.ser.filter] +public class NullSerializationTest extends AfterburnerTestBase +{ + static class NullSerializer extends JsonSerializer + { + @Override + public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) + throws IOException + { + gen.writeString("foobar"); + } + } + + static class Bean1 { + public String name = null; + } + + static class Bean2 { + public String type = null; + } + + @SuppressWarnings("serial") + static class MyNullProvider extends DefaultSerializerProvider + { + public MyNullProvider() { super(); } + public MyNullProvider(MyNullProvider base, SerializationConfig config, SerializerFactory jsf) { + super(base, config, jsf); + } + + // not really a proper impl, but has to do + @Override + public DefaultSerializerProvider copy() { + return this; + } + + @Override + public DefaultSerializerProvider createInstance(SerializationConfig config, SerializerFactory jsf) { + return new MyNullProvider(this, config, jsf); + } + + @Override + public JsonSerializer findNullValueSerializer(BeanProperty property) + throws JsonMappingException + { + if ("name".equals(property.getName())) { + return new NullSerializer(); + } + return super.findNullValueSerializer(property); + } + } + + static class BeanWithNullProps + { + @JsonSerialize(nullsUsing=NullSerializer.class) + public String a = null; + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + private final ObjectMapper MAPPER = mapperWithModule(); + + public void testSimple() throws Exception + { + assertEquals("null", MAPPER.writeValueAsString(null)); + } + + public void testOverriddenDefaultNulls() throws Exception + { + DefaultSerializerProvider sp = new DefaultSerializerProvider.Impl(); + sp.setNullValueSerializer(new NullSerializer()); + ObjectMapper m = new ObjectMapper(); + m.setSerializerProvider(sp); + assertEquals("\"foobar\"", m.writeValueAsString(null)); + } + + public void testCustomPOJONullsViaProvider() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.setSerializerProvider(new MyNullProvider()); + assertEquals("{\"name\":\"foobar\"}", m.writeValueAsString(new Bean1())); + assertEquals("{\"type\":null}", m.writeValueAsString(new Bean2())); + } + + public void testCustomTreeNullsViaProvider() throws Exception + { + ObjectNode root = MAPPER.createObjectNode(); + root.putNull("a"); + + // by default, null is... well, null + assertEquals("{\"a\":null}", MAPPER.writeValueAsString(root)); + + // but then we can customize it: + DefaultSerializerProvider prov = new MyNullProvider(); + prov.setNullValueSerializer(new NullSerializer()); + ObjectMapper m = new ObjectMapper(); + m.setSerializerProvider(prov); + assertEquals("{\"a\":\"foobar\"}", m.writeValueAsString(root)); + } + + public void testNullSerializeViaPropertyAnnotation() throws Exception + { + assertEquals("{\"a\":\"foobar\"}", MAPPER.writeValueAsString(new BeanWithNullProps())); + } +} diff --git a/release-notes/VERSION b/release-notes/VERSION index b573f075..b8436532 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -15,6 +15,7 @@ Modules: #30: (afterburner) `IncompatibleClassChangeError` deserializing interface methods with default impl (reported by Shawn S) +#33: (afterburner) `@JsonSerialize` with `nullUsing` option not working for `String` properties 2.8.10 (24-Aug-2017) 2.8.9 (12-Jun-2017)