Skip to content

Commit 21ea7f5

Browse files
authored
Fix #4963 (#4964)
1 parent ed3c44f commit 21ea7f5

File tree

5 files changed

+59
-3
lines changed

5 files changed

+59
-3
lines changed

release-notes/VERSION-2.x

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ Project: jackson-databind
4949
#4953: Allow clearing all caches to avoid classloader leaks
5050
(contributed by Joren I)
5151
#4959: Add explicit deserializer for `ThreadGroup`
52+
#4963: Serializing `Map.Entry` as Bean with `@JsonFormat.shape = Shape.OBJECT`
53+
fails on JDK 17+
5254
5355
2.18.3 (not yet released)
5456

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

+7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
1919
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
2020
import com.fasterxml.jackson.databind.ser.impl.FilteredBeanPropertyWriter;
21+
import com.fasterxml.jackson.databind.ser.impl.MapEntryAsPOJOSerializer;
2122
import com.fasterxml.jackson.databind.ser.impl.ObjectIdWriter;
2223
import com.fasterxml.jackson.databind.ser.impl.PropertyBasedObjectIdGenerator;
2324
import com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer;
@@ -394,6 +395,12 @@ protected JsonSerializer<Object> constructBeanOrAddOnSerializer(SerializerProvid
394395
if (_isUnserializableJacksonType(prov, type)) {
395396
return new ToEmptyObjectSerializer(type);
396397
}
398+
// 08-Feb-2025, tatu: [databind#4963] Need to have explicit serializer for
399+
// Map.Entry type that are from JDK (for others just use regular introspection)
400+
if (type.isTypeOrSubTypeOf(Map.Entry.class)
401+
&& ClassUtil.isJDKClass(type.getRawClass())) {
402+
return (JsonSerializer<Object>)(JsonSerializer<?>) MapEntryAsPOJOSerializer.create(prov, type);
403+
}
397404
final SerializationConfig config = prov.getConfig();
398405
BeanSerializerBuilder builder = constructBeanSerializerBuilder(beanDesc);
399406
builder.setConfig(config);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.fasterxml.jackson.databind.ser.impl;
2+
3+
import java.io.IOException;
4+
import java.util.Map;
5+
import java.util.Map.Entry;
6+
7+
import com.fasterxml.jackson.core.JsonGenerator;
8+
import com.fasterxml.jackson.databind.JavaType;
9+
import com.fasterxml.jackson.databind.SerializerProvider;
10+
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
11+
12+
/**
13+
* Serializer used to serialize Map.Entry as POJOs: that is, as if
14+
* introspected as POJOs so that there's intermediate "key" and "value"
15+
* properties.
16+
*<p>
17+
* TODO: does not fully handle contextualization, type resolution and so on.
18+
*
19+
* @since 2.19
20+
*/
21+
public class MapEntryAsPOJOSerializer extends StdSerializer<Map.Entry<?,?>>
22+
{
23+
private static final long serialVersionUID = 1L;
24+
25+
protected MapEntryAsPOJOSerializer(JavaType type) {
26+
super(type);
27+
}
28+
29+
public static MapEntryAsPOJOSerializer create(SerializerProvider ctxt,
30+
JavaType type)
31+
{
32+
return new MapEntryAsPOJOSerializer(type);
33+
}
34+
35+
@Override
36+
public void serialize(Entry<?, ?> value, JsonGenerator gen, SerializerProvider ctxt)
37+
throws IOException
38+
{
39+
gen.writeStartObject(value);
40+
gen.writeFieldName("key");
41+
ctxt.defaultSerializeValue(value.getKey(), gen);
42+
gen.writeFieldName("value");
43+
ctxt.defaultSerializeValue(value.getValue(), gen);
44+
gen.writeEndObject();
45+
}
46+
}

src/main/java/com/fasterxml/jackson/databind/ser/impl/MapEntrySerializer.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,8 @@ protected void serializeDynamic(Map.Entry<?, ?> value, JsonGenerator gen,
394394
if (valueSer.isEmpty(provider, valueElem)) {
395395
return;
396396
}
397-
} if (_suppressableValue.equals(valueElem)) {
397+
}
398+
else if (_suppressableValue.equals(valueElem)) {
398399
return;
399400
}
400401
}

src/test/java/com/fasterxml/jackson/databind/util/ClassUtilTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ public void testFindEnumTypeNonJdk()
222222
assertEquals(TestEnum.class, ClassUtil.findEnumType(TestEnum.B));
223223
}
224224

225-
// Some trouble with JDK 16+
225+
// Some trouble with JDK 17+ (unless --add-opens to force access added)
226226
@Test
227227
public void testFindEnumSetTypeJDK()
228228
{
@@ -231,7 +231,7 @@ public void testFindEnumSetTypeJDK()
231231
assertEquals(TestEnum.class, ClassUtil.findEnumType(EnumSet.noneOf(TestEnum.class)));
232232
}
233233

234-
// Some trouble with JDK 16+
234+
// Some trouble with JDK 17+ (unless --add-opens to force access added)
235235
@Test
236236
public void testFindEnumMapTypeJDK()
237237
{

0 commit comments

Comments
 (0)