在使用Jackson处理YAML格式的多态对象序列化时,默认情况下会为对象添加原生类型标签,用来标识对象的具体类型,但是这些标签往往会让生成的YAML内容变得冗余,不符合部分场景的使用需求,我们可以通过配置Jackson的相关参数来移除这些标签。

问题产生的原因
Jackson在处理多态类型序列化时,为了保证反序列化时能够正确识别对象的具体类型,会默认在生成的YAML中添加类型标识信息,也就是我们看到的原生类型标签。当我们的类存在继承关系,并且使用了@JsonTypeInfo这类注解时,这个标签会默认生成。
移除类型标签的核心方案
方案一:禁用默认类型信息配置
如果是全局的多态类型处理,我们可以通过配置ObjectMapper的PolymorphicTypeValidator和禁用默认类型信息的方式来移除标签。首先需要引入Jackson的YAML依赖:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.15.2</version>
</dependency>
然后定义父类和子类:
// 父类
public abstract class Animal {
private String name;
public Animal() {}
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// 子类Dog
public class Dog extends Animal {
private String breed;
public Dog() {}
public Dog(String name, String breed) {
super(name);
this.breed = breed;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
}
// 子类Cat
public class Cat extends Animal {
private int age;
public Cat() {}
public Cat(String name, int age) {
super(name);
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
接下来配置ObjectMapper移除类型标签:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.PolymorphicTypeValidator;
import java.util.ArrayList;
import java.util.List;
public class YamlSerializeDemo {
public static void main(String[] args) throws Exception {
// 构建类型校验器,允许Animal的子类序列化
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder()
.allowIfSubType("com.example") // 替换为你的包路径
.build();
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
// 禁用默认的类型信息包含,避免生成原生类型标签
mapper.deactivateDefaultTyping();
List<Animal> animals = new ArrayList<>();
animals.add(new Dog("小黑", "拉布拉多"));
animals.add(new Cat("小白", 2));
// 序列化输出
String yaml = mapper.writeValueAsString(animals);
System.out.println(yaml);
}
}
上述代码执行后,生成的YAML内容不会包含原生的类型标签,输出结果如下:
- name: "小黑" breed: "拉布拉多" - name: "小白" age: 2
方案二:使用注解自定义类型信息处理
如果只需要针对特定的类移除类型标签,可以使用@JsonTypeInfo注解调整类型信息的处理方式,设置include属性为JsonTypeInfo.As.NONE即可不生成类型标签:
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
public abstract class Animal {
private String name;
public Animal() {}
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
这样配置后,即使Jackson默认开启了类型信息处理,这个Animal类及其子类的序列化结果也不会包含类型标签。
注意事项
移除类型标签之后,反序列化时如果无法从内容中判断对象的具体类型,会导致反序列化失败。如果业务场景需要同时支持序列化和反序列化,建议保留必要的类型标识,或者自定义类型解析逻辑,确保反序列化时能够正确匹配到对应的子类。
另外,不同版本的Jackson配置方式可能存在细微差异,如果上述方法不生效,可以检查Jackson的版本,或者查看官方文档中对应版本的多态类型处理说明。