今天编码的时候遇到一个报错:
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进行序列化的?