Skip to content

Commit 6a3f8f4

Browse files
committed
Fix #2592
Fix will not work if filter is used as it triggers separate execution path.
1 parent 8b6cabf commit 6a3f8f4

File tree

3 files changed

+120
-28
lines changed

3 files changed

+120
-28
lines changed

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public void getAndSerialize(Object bean, JsonGenerator gen, SerializerProvider p
5959
}
6060
// 23-Feb-2015, tatu: Nasty, but has to do (for now)
6161
if (_mapSerializer != null) {
62-
_mapSerializer.serializeFields((Map<?,?>) value, gen, provider);
62+
_mapSerializer.serializeWithoutTypeInfo((Map<?,?>) value, gen, provider);
6363
return;
6464
}
6565
_serializer.serialize(value, gen, provider);

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

+16-22
Original file line numberDiff line numberDiff line change
@@ -628,21 +628,7 @@ public void serialize(Map<?,?> value, JsonGenerator gen, SerializerProvider prov
628628
throws IOException
629629
{
630630
gen.writeStartObject(value);
631-
if (!value.isEmpty()) {
632-
if (_sortKeys || provider.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
633-
value = _orderEntries(value, gen, provider);
634-
}
635-
PropertyFilter pf;
636-
if ((_filterId != null) && (pf = findPropertyFilter(provider, _filterId, value)) != null) {
637-
serializeFilteredFields(value, gen, provider, pf, _suppressableValue);
638-
} else if ((_suppressableValue != null) || _suppressNulls) {
639-
serializeOptionalFields(value, gen, provider, _suppressableValue);
640-
} else if (_valueSerializer != null) {
641-
serializeFieldsUsing(value, gen, provider, _valueSerializer);
642-
} else {
643-
serializeFields(value, gen, provider);
644-
}
645-
}
631+
serializeWithoutTypeInfo(value, gen, provider);
646632
gen.writeEndObject();
647633
}
648634

@@ -655,6 +641,21 @@ public void serializeWithType(Map<?,?> value, JsonGenerator gen, SerializerProvi
655641
gen.setCurrentValue(value);
656642
WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen,
657643
typeSer.typeId(value, JsonToken.START_OBJECT));
644+
serializeWithoutTypeInfo(value, gen, provider);
645+
typeSer.writeTypeSuffix(gen, typeIdDef);
646+
}
647+
648+
/*
649+
/**********************************************************
650+
/* Secondary serialization methods
651+
/**********************************************************
652+
*/
653+
654+
/**
655+
* General-purpose serialization for contents without writing object type. Will suppress, filter and
656+
* use custom serializers.
657+
*/
658+
public void serializeWithoutTypeInfo(Map<?, ?> value, JsonGenerator gen, SerializerProvider provider) throws IOException {
658659
if (!value.isEmpty()) {
659660
if (_sortKeys || provider.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
660661
value = _orderEntries(value, gen, provider);
@@ -670,15 +671,8 @@ public void serializeWithType(Map<?,?> value, JsonGenerator gen, SerializerProvi
670671
serializeFields(value, gen, provider);
671672
}
672673
}
673-
typeSer.writeTypeSuffix(gen, typeIdDef);
674674
}
675675

676-
/*
677-
/**********************************************************
678-
/* Secondary serialization methods
679-
/**********************************************************
680-
*/
681-
682676
/**
683677
* General-purpose serialization for contents, where we do not necessarily know
684678
* the value serialization, but

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

+103-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
package com.fasterxml.jackson.databind.ser;
22

3-
import java.io.IOException;
4-
import java.util.*;
5-
6-
import com.fasterxml.jackson.annotation.*;
3+
import com.fasterxml.jackson.annotation.JsonAnyGetter;
4+
import com.fasterxml.jackson.annotation.JsonFilter;
5+
import com.fasterxml.jackson.annotation.JsonInclude;
76
import com.fasterxml.jackson.core.JsonGenerator;
8-
import com.fasterxml.jackson.databind.*;
7+
import com.fasterxml.jackson.databind.BaseMapTest;
8+
import com.fasterxml.jackson.databind.ObjectMapper;
9+
import com.fasterxml.jackson.databind.SerializationFeature;
10+
import com.fasterxml.jackson.databind.SerializerProvider;
911
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
12+
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
13+
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
1014
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
1115
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
1216

17+
import java.io.IOException;
18+
import java.util.HashMap;
19+
import java.util.LinkedHashMap;
20+
import java.util.Map;
21+
1322
public class AnyGetterTest extends BaseMapTest
1423
{
1524
static class Bean
@@ -131,6 +140,37 @@ public void serialize(String value, JsonGenerator gen,
131140
}
132141
}
133142

143+
static class Bean2592NoAnnotations
144+
{
145+
protected Map<String, String> properties = new HashMap<>();
146+
147+
@JsonAnyGetter
148+
public Map<String, String> getProperties() {
149+
return properties;
150+
}
151+
152+
public void setProperties(Map<String, String> properties) {
153+
this.properties = properties;
154+
}
155+
156+
public void add(String key, String value) {
157+
properties.put(key, value);
158+
}
159+
}
160+
161+
static class Bean2592PropertyIncludeNonEmpty extends Bean2592NoAnnotations
162+
{
163+
@JsonInclude(content = JsonInclude.Include.NON_EMPTY)
164+
@JsonAnyGetter
165+
@Override
166+
public Map<String, String> getProperties() {
167+
return properties;
168+
}
169+
}
170+
171+
@JsonFilter("Bean2592")
172+
static class Bean2592WithFilter extends Bean2592NoAnnotations {}
173+
134174
/*
135175
/**********************************************************
136176
/* Test methods
@@ -196,4 +236,62 @@ public void testAnyGetterWithValueSerializer() throws Exception
196236
String json = mapper.writeValueAsString(input);
197237
assertEquals("{\"key\":\"VALUE\"}", json);
198238
}
239+
240+
// [databind#2592]
241+
public void testAnyGetterWithMapperDefaultIncludeNonEmpty() throws Exception
242+
{
243+
ObjectMapper mapper = new ObjectMapper()
244+
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
245+
Bean2592NoAnnotations input = new Bean2592NoAnnotations();
246+
input.add("non-empty", "property");
247+
input.add("empty", "");
248+
input.add("null", null);
249+
String json = mapper.writeValueAsString(input);
250+
assertEquals("{\"non-empty\":\"property\"}", json);
251+
}
252+
253+
// [databind#2592]
254+
public void testAnyGetterWithMapperDefaultIncludeNonEmptyAndFilterOnBean() throws Exception
255+
{
256+
FilterProvider filters = new SimpleFilterProvider()
257+
.addFilter("Bean2592", SimpleBeanPropertyFilter.serializeAllExcept("something"));
258+
ObjectMapper mapper = new ObjectMapper()
259+
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
260+
.setFilterProvider(filters);
261+
Bean2592WithFilter input = new Bean2592WithFilter();
262+
input.add("non-empty", "property");
263+
input.add("empty", "");
264+
input.add("null", null);
265+
String json = mapper.writeValueAsString(input);
266+
// Unfortunately path for bean with filter is different. It still skips nulls.
267+
assertEquals("{\"non-empty\":\"property\",\"empty\":\"\"}", json);
268+
}
269+
270+
// [databind#2592]
271+
public void testAnyGetterWithPropertyIncludeNonEmpty() throws Exception
272+
{
273+
ObjectMapper mapper = new ObjectMapper();
274+
Bean2592PropertyIncludeNonEmpty input = new Bean2592PropertyIncludeNonEmpty();
275+
input.add("non-empty", "property");
276+
input.add("empty", "");
277+
input.add("null", null);
278+
String json = mapper.writeValueAsString(input);
279+
assertEquals("{\"non-empty\":\"property\"}", json);
280+
}
281+
282+
// [databind#2592]
283+
public void testAnyGetterConfigIncludeNonEmpty() throws Exception
284+
{
285+
ObjectMapper mapper = new ObjectMapper();
286+
mapper.configOverride(Map.class).setInclude(JsonInclude.Value.construct(
287+
JsonInclude.Include.USE_DEFAULTS,
288+
JsonInclude.Include.NON_EMPTY
289+
));
290+
Bean2592NoAnnotations input = new Bean2592NoAnnotations();
291+
input.add("non-empty", "property");
292+
input.add("empty", "");
293+
input.add("null", null);
294+
String json = mapper.writeValueAsString(input);
295+
assertEquals("{\"non-empty\":\"property\"}", json);
296+
}
199297
}

0 commit comments

Comments
 (0)