jackson序列化优先级和注解顺序

jackson序列化优先级和注解顺序

先说结论:
序列化时getter方法优先于字段,注解添加到字段上或添加在getter方法上同样生效。

1. 创建serializerProvider调用serializeValue方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected final void _writeValueAndClose(JsonGenerator g, Object value)
throws IOException
{
SerializationConfig cfg = getSerializationConfig();
if (cfg.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) {
_writeCloseable(g, value, cfg);
return;
}
try {
_serializerProvider(cfg).serializeValue(g, value);
} catch (Exception e) {
ClassUtil.closeOnFailAndThrowAsIOE(g, e);
return;
}
g.close();
}

2. 获取JsonSerializer,并使用它进行序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public void serializeValue(JsonGenerator gen, Object value) throws IOException
{
_generator = gen;
if (value == null) {
_serializeNull(gen);
return;
}
final Class<?> cls = value.getClass();
// true, since we do want to cache root-level typed serializers (ditto for null property)
final JsonSerializer<Object> ser = findTypedValueSerializer(cls, true, null);
PropertyName rootName = _config.getFullRootName();
if (rootName == null) { // not explicitly specified
if (_config.isEnabled(SerializationFeature.WRAP_ROOT_VALUE)) {
_serialize(gen, value, ser, _config.findRootName(cls));
return;
}
} else if (!rootName.isEmpty()) {
_serialize(gen, value, ser, rootName);
return;
}
_serialize(gen, value, ser);
}

3. 此方法核心在第二行,会创建BeanDescription

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public JsonSerializer<Object> createSerializer(SerializerProvider prov,
JavaType origType)
throws JsonMappingException
{
// Very first thing, let's check if there is explicit serializer annotation:
final SerializationConfig config = prov.getConfig();
BeanDescription beanDesc = config.introspect(origType);
JsonSerializer<?> ser = findSerializerFromAnnotation(prov, beanDesc.getClassInfo());
if (ser != null) {
return (JsonSerializer<Object>) ser;
}
boolean staticTyping;
// Next: we may have annotations that further indicate actual type to use (a super type)
final AnnotationIntrospector intr = config.getAnnotationIntrospector();
JavaType type;

if (intr == null) {
type = origType;
} else {
try {
type = intr.refineSerializationType(config, beanDesc.getClassInfo(), origType);
} catch (JsonMappingException e) {
return prov.reportBadTypeDefinition(beanDesc, e.getMessage());
}
}
if (type == origType) { // no changes, won't force static typing
staticTyping = false;
} else { // changes; assume static typing; plus, need to re-introspect if class differs
staticTyping = true;
if (!type.hasRawClass(origType.getRawClass())) {
beanDesc = config.introspect(type);
}
}
// Slight detour: do we have a Converter to consider?
Converter<Object,Object> conv = beanDesc.findSerializationConverter();
if (conv == null) { // no, simple
return (JsonSerializer<Object>) _createSerializer2(prov, type, beanDesc, staticTyping);
}
JavaType delegateType = conv.getOutputType(prov.getTypeFactory());

// One more twist, as per [databind#288]; probably need to get new BeanDesc
if (!delegateType.hasRawClass(type.getRawClass())) {
beanDesc = config.introspect(delegateType);
// [#359]: explicitly check (again) for @JsonSerializer...
ser = findSerializerFromAnnotation(prov, beanDesc.getClassInfo());
}
// [databind#731]: Should skip if nominally java.lang.Object
if (ser == null && !delegateType.isJavaLangObject()) {
ser = _createSerializer2(prov, delegateType, beanDesc, true);
}
return new StdDelegatingSerializer(conv, delegateType, ser);
}

4. BeanDescription内的findProperties方法,

此方法触发时将对class进行解析,解析过程如下,这里就解释了注解加在字段上或方法上同样生效的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected void collectAll()
{
LinkedHashMap<String, POJOPropertyBuilder> props = new LinkedHashMap<String, POJOPropertyBuilder>();

//使用反射获取字段
_addFields(props);

//使用反射获取getter,setter方法
_addMethods(props);

//合并注解,此处会将方法上的注解和字段上的注解进行合并在一起,这就解释了注解加在字段和方法上同样有效
for (POJOPropertyBuilder property : props.values()) {
property.mergeAnnotations(_forSerialization);
}
_properties = props;
_collected = true;
}

5. 为何方法优于字段

在BeanSerializerFactory方法中存在下面方法,会从BeanPropertyDefinition中构建AnnotatedMember,而getAccessor()方法是优先检测getter方法再检测field,故序列化时方法优先于字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
protected List<BeanPropertyWriter> findBeanProperties(SerializerProvider prov,
BeanDescription beanDesc, BeanSerializerBuilder builder)
throws JsonMappingException
{
List<BeanPropertyDefinition> properties = beanDesc.findProperties();
final SerializationConfig config = prov.getConfig();

// ignore specified types
removeIgnorableTypes(config, beanDesc, properties);

// and possibly remove ones without matching mutator...
if (config.isEnabled(MapperFeature.REQUIRE_SETTERS_FOR_GETTERS)) {
removeSetterlessGetters(config, beanDesc, properties);
}

// nothing? can't proceed (caller may or may not throw an exception)
if (properties.isEmpty()) {
return null;
}
// null is for value type serializer, which we don't have access to from here (ditto for bean prop)
boolean staticTyping = usesStaticTyping(config, beanDesc, null);
PropertyBuilder pb = constructPropertyBuilder(config, beanDesc);

ArrayList<BeanPropertyWriter> result = new ArrayList<BeanPropertyWriter>(properties.size());
for (BeanPropertyDefinition property : properties) {
final AnnotatedMember accessor = property.getAccessor();
// Type id? Requires special handling:
if (property.isTypeId()) {
if (accessor != null) {
builder.setTypeId(accessor);
}
continue;
}
// suppress writing of back references
AnnotationIntrospector.ReferenceProperty refType = property.findReferenceType();
if (refType != null && refType.isBackReference()) {
continue;
}
if (accessor instanceof AnnotatedMethod) {
result.add(_constructWriter(prov, property, pb, staticTyping, (AnnotatedMethod) accessor));
} else {
result.add(_constructWriter(prov, property, pb, staticTyping, (AnnotatedField) accessor));
}
}
return result;
}


public AnnotatedMember getAccessor(){
AnnotatedMember m = getGetter();
if (m == null) {
m = getField();
}
return m;
}


jackson序列化优先级和注解顺序
https://www.huangchaoyu.com/2508935463.html
作者
hcy
发布于
2022年4月19日
更新于
2024年8月17日
许可协议