Java 杰克逊';s多态序列化/反序列化和自定义序列化程序/反序列化程序

Java 杰克逊';s多态序列化/反序列化和自定义序列化程序/反序列化程序,java,json,jackson,Java,Json,Jackson,I'va是一个OID接口,可以由许多具体类型实现: 公共接口OID{ } 公共抽象类库 工具类{ 私有字符串_id; } 公共类肌球蛋白 扩大了基础{ 公共肌瘤{ //默认无参数构造函数 } } 公共级肌瘤 扩大了基础{ 公共肌瘤{ //默认无参数构造函数 } } 现在我有了一个具有两个字段的对象,一个使用抽象接口类型(OID)定义,另一个使用具体类型(MyOID)定义 公共类MyBean{ 私有OID _绝对ID; 私人类肌瘤; 公共MyBean(最终OID绝对值,最终MyOID具体值){

I'va是一个OID接口,可以由许多具体类型实现:

公共接口OID{
}
公共抽象类库
工具类{
私有字符串_id;
}
公共类肌球蛋白
扩大了基础{
公共肌瘤{
//默认无参数构造函数
}
}
公共级肌瘤
扩大了基础{
公共肌瘤{
//默认无参数构造函数
}
}
现在我有了一个具有两个字段的对象,一个使用抽象接口类型(OID)定义,另一个使用具体类型(MyOID)定义

公共类MyBean{
私有OID _绝对ID;
私人类肌瘤;
公共MyBean(最终OID绝对值,最终MyOID具体值){
_绝对ID=绝对ID;
_concreteOid=concreteOid;
}
}
我想使用jackson以不同的方式序列化/反序列化字段,无论它们是使用抽象接口类型还是具体类型定义的:

{
“_absOid”:{
“类型”:“肌瘤样”,
“id”:“\u和\u id\u”
},
“\u concreteOid”:“\u另一个\u id\u”
}
注意,
\u absOid
被序列化,包括类型信息(多态序列化),而
\u concretoid
被序列化为文本

为此,我将OID接口注释为:

@JsonSubTypes({
@JsonSubTypes.Type(MyOID.class),
@JsonSubTypes.Type(MyOtherOID.class)
})
公共接口OID{
}
并为每个具体类型分配了类型id:

@JsonTypeName(“MyOID”)
公共类肌球蛋白
扩大了基础{
...
}
@JsonTypeName(“MyOtherOID”)
公共级肌瘤
扩大了基础{
...
}
最后,对容器bean中的抽象定义字段进行注释,使其包含类型信息:

公共类MyBean{
@JsonTypeInfo(include=JsonTypeInfo.As.PROPERTY,
use=JsonTypeInfo.Id.NAME,
property=“type”)
私有OID _绝对ID;
私人类肌瘤;
}
到目前为止,还不错,但是如果字段是使用抽象类型(OID)定义的,而字段是使用具体类型(MyOID)定义的,那么为了实现不同的序列化,我必须创建一个自定义序列化程序:

首先注释要使用序列化器/反序列化器的具体类型:

@JsonTypeName(“MyOID”)
@JsonSerialize(使用=OIDSerializer.class)@JsonDeserialize(使用=OIDSerializer.class)
公共类肌球蛋白
扩大了基础{
...
}
@JsonTypeName(“MyOtherOID”)
@JsonSerialize(使用=OIDSerializer.class)@JsonDeserialize(使用=OIDSerializer.class)
公共级肌瘤
扩大了基础{
...
}
。。。序列化程序/反序列化程序代码:

公共静态类序列化程序
扩展JsonSerializer{
@凌驾
public void serialize(最终OID值,
最终JSONG发电机jgen,
最终SerializerProvider提供程序)引发IOException、JsonProcessingException{
//****序列化具体类型时使用
jgen.writeString(value.toString());
}
@凌驾
public void serializeWithType(最终OID值,
最终JSONG发电机jgen,
最终序列化提供程序提供程序,
最终类型序列化程序(typeSer)引发IOException{
//****序列化多态类型时使用
//猜猜类型id
WritableTypeId-typeId=typeSer.typeId(值,JsonToken.START\u对象);
//类型前缀
类型SER.writeTypePrefix(jgen,
类型ID);
//反对
jgen.writeFieldName(“id”);
jgen.writeString(value.toString());
//类型后缀
typeId.WrapperWrited=!jgen.canWriteTypeId();
类型SER.writeTypeSuffix(jgen,
类型ID);
}
}
当对json字符串进行反序列化时,出现了问题,我使用了以下自定义反序列化程序:

公共静态类反序列化器
扩展StdDeserializer{
公共MyOIDDeSerializer(){
超级(类肌类);
} 
@凌驾
公共OID反序列化(最终JsonParser jp,
最终反序列化上下文(ctxt)引发IOException,JsonProcessingException{
JsonNode节点=jp.getCodec().readTree(jp);
//[1]-根据序列化格式读取id
字符串oidStr=null;
//text node>concrete oid impl序列化为[value]
if(node.getNodeType()==JsonNodeType.STRING){
oidStr=((TextNode)节点).asText();
}
//oid=value>抽象oid impl序列化为{typeId=[type],oid={value]}
否则{
ObjectNode objNode=(ObjectNode)节点;
oidStr=objNode.findValue(“id”).asText();
}
//[2]-读取类型id
字符串typeId=objNode.findValue(“type”).asText()
//问题!!!!!!
//如何从typeId获取类型以创建具体实例
//如何访问类型解析程序????
Class您可以尝试以下方法:

AnnotationIntrospector annotationInspector = new JacksonAnnotationIntrospector();
AnnotatedClass annotatedClass = AnnotatedClass.constructWithoutSuperTypes(OID.class,
                new ObjectMapper().getSerializationConfig());
List<NamedType> subtypes = annotationInspector.findSubtypes(annotatedClass);

for(NamedType type: subtypes){
    if(type.getType().getName().contains(typeId)){
        return type.getClass().newInstance();   
    }

}
AnnotationIntrospector annotationInspector=新JacksonAnnotationIntrospector();
AnnotatedClass AnnotatedClass=AnnotatedClass.ConstructionWithoutSuperTypes(OID.class,
新的ObjectMapper().getSerializationConfig());
列表子类型=annotationInspector.findSubtypes(annotatedClass);
for(NamedType类型:子类型){
if(type.getType().getName().contains(typeId)){
返回类型.getClass().newInstance();
}
}

序列化程序必须知道,字段可能与类型信息一起序列化(当使用抽象类型声明字段时)