Skip to content

Commit

Permalink
Fix #2592: JsonInclude support for any getters
Browse files Browse the repository at this point in the history
Fix will not work if filter is used as it triggers separate
execution path.
  • Loading branch information
akhomchenko authored and cowtowncoder committed Feb 5, 2020
1 parent 8b6cabf commit f8d34e2
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public void getAndSerialize(Object bean, JsonGenerator gen, SerializerProvider p
}
// 23-Feb-2015, tatu: Nasty, but has to do (for now)
if (_mapSerializer != null) {
_mapSerializer.serializeFields((Map<?,?>) value, gen, provider);
_mapSerializer.serializeWithoutTypeInfo((Map<?,?>) value, gen, provider);
return;
}
_serializer.serialize(value, gen, provider);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -628,21 +628,7 @@ public void serialize(Map<?,?> value, JsonGenerator gen, SerializerProvider prov
throws IOException
{
gen.writeStartObject(value);
if (!value.isEmpty()) {
if (_sortKeys || provider.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
value = _orderEntries(value, gen, provider);
}
PropertyFilter pf;
if ((_filterId != null) && (pf = findPropertyFilter(provider, _filterId, value)) != null) {
serializeFilteredFields(value, gen, provider, pf, _suppressableValue);
} else if ((_suppressableValue != null) || _suppressNulls) {
serializeOptionalFields(value, gen, provider, _suppressableValue);
} else if (_valueSerializer != null) {
serializeFieldsUsing(value, gen, provider, _valueSerializer);
} else {
serializeFields(value, gen, provider);
}
}
serializeWithoutTypeInfo(value, gen, provider);
gen.writeEndObject();
}

Expand All @@ -655,6 +641,21 @@ public void serializeWithType(Map<?,?> value, JsonGenerator gen, SerializerProvi
gen.setCurrentValue(value);
WritableTypeId typeIdDef = typeSer.writeTypePrefix(gen,
typeSer.typeId(value, JsonToken.START_OBJECT));
serializeWithoutTypeInfo(value, gen, provider);
typeSer.writeTypeSuffix(gen, typeIdDef);
}

/*
/**********************************************************
/* Secondary serialization methods
/**********************************************************
*/

/**
* General-purpose serialization for contents without writing object type. Will suppress, filter and
* use custom serializers.
*/
public void serializeWithoutTypeInfo(Map<?, ?> value, JsonGenerator gen, SerializerProvider provider) throws IOException {
if (!value.isEmpty()) {
if (_sortKeys || provider.isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
value = _orderEntries(value, gen, provider);
Expand All @@ -670,15 +671,8 @@ public void serializeWithType(Map<?,?> value, JsonGenerator gen, SerializerProvi
serializeFields(value, gen, provider);
}
}
typeSer.writeTypeSuffix(gen, typeIdDef);
}

/*
/**********************************************************
/* Secondary serialization methods
/**********************************************************
*/

/**
* General-purpose serialization for contents, where we do not necessarily know
* the value serialization, but
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.impl.*;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
Expand Down Expand Up @@ -131,6 +132,37 @@ public void serialize(String value, JsonGenerator gen,
}
}

static class Bean2592NoAnnotations
{
protected Map<String, String> properties = new HashMap<>();

@JsonAnyGetter
public Map<String, String> getProperties() {
return properties;
}

public void setProperties(Map<String, String> properties) {
this.properties = properties;
}

public void add(String key, String value) {
properties.put(key, value);
}
}

static class Bean2592PropertyIncludeNonEmpty extends Bean2592NoAnnotations
{
@JsonInclude(content = JsonInclude.Include.NON_EMPTY)
@JsonAnyGetter
@Override
public Map<String, String> getProperties() {
return properties;
}
}

@JsonFilter("Bean2592")
static class Bean2592WithFilter extends Bean2592NoAnnotations {}

/*
/**********************************************************
/* Test methods
Expand Down Expand Up @@ -196,4 +228,62 @@ public void testAnyGetterWithValueSerializer() throws Exception
String json = mapper.writeValueAsString(input);
assertEquals("{\"key\":\"VALUE\"}", json);
}

// [databind#2592]
public void testAnyGetterWithMapperDefaultIncludeNonEmpty() throws Exception
{
ObjectMapper mapper = new ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
Bean2592NoAnnotations input = new Bean2592NoAnnotations();
input.add("non-empty", "property");
input.add("empty", "");
input.add("null", null);
String json = mapper.writeValueAsString(input);
assertEquals("{\"non-empty\":\"property\"}", json);
}

// [databind#2592]
public void testAnyGetterWithMapperDefaultIncludeNonEmptyAndFilterOnBean() throws Exception
{
FilterProvider filters = new SimpleFilterProvider()
.addFilter("Bean2592", SimpleBeanPropertyFilter.serializeAllExcept("something"));
ObjectMapper mapper = new ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
.setFilterProvider(filters);
Bean2592WithFilter input = new Bean2592WithFilter();
input.add("non-empty", "property");
input.add("empty", "");
input.add("null", null);
String json = mapper.writeValueAsString(input);
// Unfortunately path for bean with filter is different. It still skips nulls.
assertEquals("{\"non-empty\":\"property\",\"empty\":\"\"}", json);
}

// [databind#2592]
public void testAnyGetterWithPropertyIncludeNonEmpty() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
Bean2592PropertyIncludeNonEmpty input = new Bean2592PropertyIncludeNonEmpty();
input.add("non-empty", "property");
input.add("empty", "");
input.add("null", null);
String json = mapper.writeValueAsString(input);
assertEquals("{\"non-empty\":\"property\"}", json);
}

// [databind#2592]
public void testAnyGetterConfigIncludeNonEmpty() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
mapper.configOverride(Map.class).setInclude(JsonInclude.Value.construct(
JsonInclude.Include.USE_DEFAULTS,
JsonInclude.Include.NON_EMPTY
));
Bean2592NoAnnotations input = new Bean2592NoAnnotations();
input.add("non-empty", "property");
input.add("empty", "");
input.add("null", null);
String json = mapper.writeValueAsString(input);
assertEquals("{\"non-empty\":\"property\"}", json);
}
}

0 comments on commit f8d34e2

Please sign in to comment.