Skip to content

Commit

Permalink
Merge branch '2.16' into 2.17
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Jun 7, 2024
2 parents 11f9b4a + ee39f3e commit a01d01f
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 13 deletions.
5 changes: 4 additions & 1 deletion release-notes/CREDITS-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -1739,6 +1739,10 @@ Stephane Bailliez (sbailliez@github)
leads to `InvalidDefinitionException`: Multiple fields representing property
(2.16.2)

Guillaume Jardillier (Mugiwara84@github)
* Reported #4564: Possible 2.16.0 Enum-as-JSON-Object serialization regression
(2.16.3)

Muhammad Khalikov (mukham12@github)
* Contributed fix for #4209: Make `BeanDeserializerModifier`/`BeanSerializerModifier`
implement `java.io.Serializable`
Expand Down Expand Up @@ -1770,4 +1774,3 @@ Oddbjørn Kvalsund (oddbjornkvalsund@github)
* Reported, contributed fix for #4430: Use `ReentrantLock` instead of `synchronized`
in `DeserializerCache` to avoid deadlock on pinning
(2.17.1)

6 changes: 6 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ Project: jackson-databind
(suggested by András P)
- JUnit5 upgraded to 5.10.1
2.16.3 (not yet released)
#4564: Possible 2.16.0 Enum-as-JSON-Object serialization regression
(reported by Guillaume J)
(fix contributed by Joo-Hyuk K)
2.16.2 (09-Mar-2024)
#4302: Problem deserializing some type of Enums when using `PropertyNamingStrategy`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,18 @@ private void _addFieldMixIns(Class<?> mixInCls, Class<?> targetClass,

private boolean _isIncludableField(Field f)
{
// [databind#2787]: Allow `Enum` mixins
// [databind#2787]: To allow `Enum` mixins, need to include Enum constants even
// to they are static fields, not instance ones.
if (f.isEnumConstant()) {
return true;
}
// Most likely synthetic fields, if any, are to be skipped similar to methods
if (f.isSynthetic()) {
return false;
}
// Static fields are never included. Transient are (since 2.6), for
// purpose of propagating removal
int mods = f.getModifiers();
if (Modifier.isStatic(mods)) {
// Static fields are never included (except for above-mentioned Enum constants.
// Transient are (since 2.6), for purpose of propagating removal
if (Modifier.isStatic(f.getModifiers())) {
return false;
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,7 @@ protected JsonSerializer<?> buildEnumSerializer(SerializationConfig config,
((BasicBeanDescription) beanDesc).removeProperty("declaringClass");
// [databind#2787]: remove self-referencing enum fields introduced by annotation flattening of mixins
if (type.isEnumType()){
_removeEnumSelfReferences(((BasicBeanDescription) beanDesc));
_removeEnumSelfReferences(beanDesc);
}
// returning null will mean that eventually BeanSerializer gets constructed
return null;
Expand All @@ -1226,24 +1226,28 @@ protected JsonSerializer<?> buildEnumSerializer(SerializationConfig config,
}

/**
* Helper method used for serialization {@link Enum} as {@link JsonFormat.Shape#OBJECT}. Removes any
* self-referencing properties from its bean description before it is transformed into a JSON Object
* as configured by {@link JsonFormat.Shape#OBJECT}.
* Helper method used for serialization {@link Enum} as {@link JsonFormat.Shape#OBJECT}.
* Removes any self-referencing properties from its bean description before it is
* transformed into a JSON Object as configured by {@link JsonFormat.Shape#OBJECT}.
* <p>
* Internally, this method iterates through {@link BeanDescription#findProperties()} and removes self.
* Internally, this method iterates through {@link BeanDescription#findProperties()}
* and removes self references.
*
* @param beanDesc the bean description to remove Enum properties from.
*
* @since 2.16
*/
private void _removeEnumSelfReferences(BasicBeanDescription beanDesc) {
private void _removeEnumSelfReferences(BeanDescription beanDesc) {
Class<?> aClass = ClassUtil.findEnumType(beanDesc.getBeanClass());
Iterator<BeanPropertyDefinition> it = beanDesc.findProperties().iterator();
while (it.hasNext()) {
BeanPropertyDefinition property = it.next();
JavaType propType = property.getPrimaryType();
// is the property a self-reference?
if (propType.isEnumType() && propType.isTypeOrSubTypeOf(aClass)) {
if (propType.isEnumType() && propType.isTypeOrSubTypeOf(aClass)
// [databind#4564] Since 2.16.3, Enum's should allow self as field, so let's remove only if static.
&& property.getAccessor().isStatic())
{
it.remove();
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.fasterxml.jackson.databind.ser.enums;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

// [databind#4564] Fix Enum-asJSON-Object serialization with self as field.
public class EnumAsFormatObject4564Test
{

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
@JsonInclude(JsonInclude.Include.NON_NULL)
public enum Level {
LEVEL1("level1"),
LEVEL2("level2"),
LEVEL3("level3", Level.LEVEL1);

public String label;
public Level sublevel;

Level(String level2) {
this.label = level2;
}

Level(String level3, Level level) {
this.label = level3;
this.sublevel = level;
}
}

private final ObjectMapper MAPPER = new JsonMapper();

@Test
public void testEnumAsFormatObject() throws JsonProcessingException {
List<Level> levels = new ArrayList<>();
levels.add(Level.LEVEL1);
levels.add(Level.LEVEL2);
levels.add(Level.LEVEL3);

String JSON = MAPPER.writerFor(new TypeReference<List<Level>>() {
}).writeValueAsString(levels);

// Fails, because we get [{"label":"level1"},{"label":"level2"},{"label":"level3"}]
assertEquals(
"["
+ "{\"label\":\"level1\"},"
+ "{\"label\":\"level2\"},"
+ "{\"label\":\"level3\",\"sublevel\":{\"label\":\"level1\"}}"
+ "]",
JSON);
}
}

0 comments on commit a01d01f

Please sign in to comment.