問題描述
今天編碼的時候遇到一個報錯:
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: No serializer found for class XXX and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class XXX and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
大概意思就是在序列化的時候對於類 XXX 沒有找到序列化器,並且沒有發現有相應的屬性來創建BeanSerializer
序列化器。
出現原因
類XXX中忘記加@Getter
註解,也就是沒有生成Getter
方法,其實這個問題到這裏就可以結束了,但是我還處於知其然不知其所以然的情況中,所以我決定繼續學習源碼,爲了瞭解問題更深層次的原因!這與JackSon
序列化的過程有關係:
public void serializeAsField(Object bean, JsonGenerator gen,
SerializerProvider prov) throws Exception {
// inlined 'get()'
final Object value = (_accessorMethod == null) ? _field.get(bean)
: _accessorMethod.invoke(bean, (Object[]) null);
// Null handling is bit different, check that first
if (value == null) {
if (_nullSerializer != null) {
gen.writeFieldName(_name);
_nullSerializer.serialize(null, gen, prov);
}
return;
}
// then find serializer to use
JsonSerializer<Object> ser = _serializer;
if (ser == null) {
Class<?> cls = value.getClass();
PropertySerializerMap m = _dynamicSerializers;
ser = m.serializerFor(cls);
if (ser == null) {
ser = _findAndAddDynamic(m, cls, prov);
}
}
// and then see if we must suppress certain values (default, empty)
if (_suppressableValue != null) {
if (MARKER_FOR_EMPTY == _suppressableValue) {
if (ser.isEmpty(prov, value)) {
return;
}
} else if (_suppressableValue.equals(value)) {
return;
}
}
// For non-nulls: simple check for direct cycles
if (value == bean) {
// three choices: exception; handled by call; or pass-through
if (_handleSelfReference(bean, gen, prov, ser)) {
return;
}
}
gen.writeFieldName(_name);
if (_typeSerializer == null) {
// 這邊是沒有找到序列化器走的分支(1)
ser.serialize(value, gen, prov);
} else {
ser.serializeWithType(value, gen, prov, _typeSerializer);
}
}
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException
{
// 判斷一下 SerializationFeature.FAIL_ON_EMPTY_BEANS(2)
// 27-Nov-2009, tatu: As per [JACKSON-201] may or may not fail...
if (provider.isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) {
// 拋出異常(3)
failForEmpty(provider, value);
}
// But if it's fine, we'll just output empty JSON Object:
gen.writeStartObject();
gen.writeEndObject();
}
protected void failForEmpty(SerializerProvider prov, Object value)
throws JsonMappingException {
prov.reportMappingProblem("No serializer found for class %s and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)",
value.getClass().getName());
}
其中序列化器爲類BeanPropertyWriter
的屬性。
/**
* If property being serialized needs type information to be included this
* is the type serializer to use. Declared type (possibly augmented with
* annotations) of property is used for determining exact mechanism to use
* (compared to actual runtime type used for serializing actual state).
*/
protected TypeSerializer _typeSerializer;
解決方案
在類XXX中增加註解,問題得到解決:
如果確實想生成一個空的Bean
,異常中也給出了一個解決方案就是禁用SerializationFeature.FAIL_ON_EMPTY_BEANS
,這個屬性默認是true
,可以在SpringCloud的全局配置文件application.yml中加入瞭如下配置:
spring:
jackson:
serialization:
FAIL_ON_EMPTY_BEANS: false
這樣則不會拋異常,最終序列化出來的結果是{}
。
參考
Jackson序列化沒有get, Set方法的POJO
No serializer found for class 類名 and no properties discovered to create BeanSerializer
spring boot 是如何利用jackson進行序列化的?