Я использую Spring Boot
, и у меня возникает ошибка при попытке преобразовать Bean
в JSON с Jackson
.
Когда эта функция (которая находится внутри @RestController
)вызываемый в первый раз, он отлично работает:
@GetMapping
public UserDto getUser() {
UserDto userDto = // get the user
// userDto.getRoles() is an enum, let's call it XEnum, with 20 entries
return userDto;
}
После этого новое значение динамически добавляется к XEnum
, поэтому это перечисление теперь имеет 21 запись.
КогдаВызывается функция выше, я получаю эту ошибку:
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: 41; nested exception is com.fasterxml.jackson.databind.JsonMappingException: 41 (through reference chain: ...UserDto["roles"]->java.util.ArrayList[21])
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:296)
at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:103)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:290)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:180)
...
Caused by: java.lang.ArrayIndexOutOfBoundsException: 41
at com.fasterxml.jackson.databind.util.EnumValues.serializedValueFor(EnumValues.java:79)
at com.fasterxml.jackson.databind.ser.std.EnumSerializer.serialize(EnumSerializer.java:132)
at com.fasterxml.jackson.databind.ser.std.EnumSerializer.serialize(EnumSerializer.java:27)
at com.fasterxml.jackson.databind.ser.impl.IndexedListSerializer.serializeContentsUsing(IndexedListSerializer.java:142)
В моем реальном случае 41
- порядковый номер новой записи в перечислении.
Класс UserDto
выглядит так:
public class UserDto implements Serializable {
private static final long serialVersionUID = 475464704956181923L;
private XEnum currentRole;
private List<XEnum> roles;
...
}
Есть ли у Джексона кеш перечисления и, следовательно, он не может найти новое значение? Если это так, могу ли я обновить его?
РЕДАКТИРОВАТЬ:
Я нашел источник проблемы.
Внутри Джексона EnumSerializer
, используемого во время сериализации, serialize
Метод выглядит следующим образом:
@Override
public final void serialize(Enum<?> en, JsonGenerator gen, SerializerProvider serializers)
throws IOException
{
// [JACKSON-684]: serialize as index?
if (_serializeAsIndex(serializers)) {
gen.writeNumber(en.ordinal());
return;
}
// [databind#749]: or via toString()?
if (serializers.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) {
gen.writeString(en.toString());
return;
}
gen.writeString(_values.serializedValueFor(en)); // this line is evaluated !!
}
_values
содержит предварительно разрешенные значения и не содержит новую запись Enum
.
Есть ли способ включить SerializationFeature.WRITE_ENUMS_USING_TO_STRING
только длянекоторые EnumSerializer
? Потому что это может иметь побочные эффекты, если я включу его глобально.