Skip to content

Commit 86cf6d0

Browse files
authored
StdDelegatingSerializer does not consider a Converter that may return null for a non-null input (#4576)
1 parent 2fdcf7e commit 86cf6d0

File tree

2 files changed

+90
-9
lines changed

2 files changed

+90
-9
lines changed

src/main/java/com/fasterxml/jackson/databind/ser/std/StdDelegatingSerializer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,11 @@ public void serializeWithType(Object value, JsonGenerator gen, SerializerProvide
174174
// 03-Oct-2012, tatu: This is actually unlikely to work ok... but for now,
175175
// let's give it a chance?
176176
Object delegateValue = convertValue(value);
177+
// consider null (to be consistent with serialize method above)
178+
if (delegateValue == null) {
179+
provider.defaultSerializeNull(gen);
180+
return;
181+
}
177182
JsonSerializer<Object> ser = _delegateSerializer;
178183
if (ser == null) {
179184
ser = _findSerializer(value, provider);

src/test/java/com/fasterxml/jackson/databind/ser/TestCustomSerializers.java

Lines changed: 85 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@
99
import org.junit.jupiter.api.Test;
1010
import org.w3c.dom.Element;
1111

12-
import com.fasterxml.jackson.annotation.JsonFilter;
13-
import com.fasterxml.jackson.annotation.JsonFormat;
14-
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
12+
import com.fasterxml.jackson.annotation.*;
1513

1614
import com.fasterxml.jackson.core.*;
1715
import com.fasterxml.jackson.core.io.CharacterEscapes;
@@ -25,6 +23,8 @@
2523
import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer;
2624
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
2725
import com.fasterxml.jackson.databind.testutil.DatabindTestUtil;
26+
import com.fasterxml.jackson.databind.type.TypeFactory;
27+
import com.fasterxml.jackson.databind.util.Converter;
2828
import com.fasterxml.jackson.databind.util.StdConverter;
2929

3030
import static org.junit.jupiter.api.Assertions.*;
@@ -191,6 +191,55 @@ public String getId() {
191191
}
192192
}
193193

194+
// [databind#4575]
195+
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type")
196+
@JsonSubTypes(
197+
{
198+
@JsonSubTypes.Type(Sub4575.class)
199+
}
200+
)
201+
@JsonTypeName("Super")
202+
static class Super4575 {
203+
public static final Super4575 NULL = new Super4575();
204+
}
205+
206+
@JsonTypeName("Sub")
207+
static class Sub4575 extends Super4575 { }
208+
209+
static class NullSerializer4575 extends StdDelegatingSerializer {
210+
public NullSerializer4575(Converter<Object, ?> converter, JavaType delegateType, JsonSerializer<?> delegateSerializer) {
211+
super(converter, delegateType, delegateSerializer);
212+
}
213+
214+
public NullSerializer4575(TypeFactory typeFactory, JsonSerializer<?> delegateSerializer) {
215+
this(
216+
new Converter<Object, Object>() {
217+
@Override
218+
public Object convert(Object value) {
219+
return value == Super4575.NULL ? null : value;
220+
}
221+
222+
@Override
223+
public JavaType getInputType(TypeFactory typeFactory) {
224+
return typeFactory.constructType(delegateSerializer.handledType());
225+
}
226+
227+
@Override
228+
public JavaType getOutputType(TypeFactory typeFactory) {
229+
return typeFactory.constructType(delegateSerializer.handledType());
230+
}
231+
},
232+
typeFactory.constructType(delegateSerializer.handledType() == null ? Object.class : delegateSerializer.handledType()),
233+
delegateSerializer
234+
);
235+
}
236+
237+
@Override
238+
protected StdDelegatingSerializer withDelegate(Converter<Object, ?> converter, JavaType delegateType, JsonSerializer<?> delegateSerializer) {
239+
return new NullSerializer4575(converter, delegateType, delegateSerializer);
240+
}
241+
}
242+
194243
/*
195244
/**********************************************************
196245
/* Unit tests
@@ -214,7 +263,6 @@ public void testCustomization() throws Exception
214263
@Test
215264
public void testCustomLists() throws Exception
216265
{
217-
ObjectMapper mapper = new ObjectMapper();
218266
SimpleModule module = new SimpleModule("test", Version.unknownVersion());
219267
JsonSerializer<?> ser = new CollectionSerializer(null, false, null, null);
220268
final JsonSerializer<Object> collectionSerializer = (JsonSerializer<Object>) ser;
@@ -231,15 +279,16 @@ public void serialize(Collection value, JsonGenerator gen, SerializerProvider pr
231279
}
232280
}
233281
});
234-
mapper.registerModule(module);
282+
ObjectMapper mapper = jsonMapperBuilder()
283+
.addModule(module)
284+
.build();
235285
assertEquals("null", mapper.writeValueAsString(new ArrayList<Object>()));
236286
}
237287

238288
// [databind#87]: delegating serializer
239289
@Test
240290
public void testDelegating() throws Exception
241291
{
242-
ObjectMapper mapper = new ObjectMapper();
243292
SimpleModule module = new SimpleModule("test", Version.unknownVersion());
244293
module.addSerializer(new StdDelegatingSerializer(Immutable.class,
245294
new StdConverter<Immutable, Map<String,Integer>>() {
@@ -252,7 +301,9 @@ public Map<String, Integer> convert(Immutable value)
252301
return map;
253302
}
254303
}));
255-
mapper.registerModule(module);
304+
ObjectMapper mapper = jsonMapperBuilder()
305+
.addModule(module)
306+
.build();
256307
assertEquals("{\"x\":3,\"y\":7}", mapper.writeValueAsString(new Immutable()));
257308
}
258309

@@ -290,8 +341,9 @@ public void testWithCustomElements() throws Exception
290341

291342
SimpleModule module = new SimpleModule("test", Version.unknownVersion());
292343
module.addSerializer(String.class, new UCStringSerializer());
293-
ObjectMapper mapper = new ObjectMapper()
294-
.registerModule(module);
344+
ObjectMapper mapper = jsonMapperBuilder()
345+
.addModule(module)
346+
.build();
295347

296348
assertEquals(q("FOOBAR"), mapper.writeValueAsString("foobar"));
297349
assertEquals(a2q("['FOO',null]"),
@@ -318,4 +370,28 @@ public void testIssue2475() throws Exception {
318370
assertEquals(a2q("{'id':'ID-2','set':[]}"),
319371
writer.writeValueAsString(new Item2475(new HashSet<String>(), "ID-2")));
320372
}
373+
374+
@Test
375+
public void testIssue4575() throws Exception {
376+
com.fasterxml.jackson.databind.Module module = new SimpleModule() {
377+
{
378+
setSerializerModifier(new BeanSerializerModifier() {
379+
@Override
380+
public JsonSerializer<?> modifySerializer(
381+
SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer
382+
) {
383+
return new NullSerializer4575(config.getTypeFactory(), serializer);
384+
}
385+
});
386+
}
387+
};
388+
389+
ObjectMapper mapper = jsonMapperBuilder()
390+
.addModule(module)
391+
.build();
392+
393+
assertEquals("{\"@type\":\"Super\"}", mapper.writeValueAsString(new Super4575()));
394+
assertEquals("{\"@type\":\"Sub\"}", mapper.writeValueAsString(new Sub4575()));
395+
assertEquals("null", mapper.writeValueAsString(Super4575.NULL));
396+
}
321397
}

0 commit comments

Comments
 (0)