我有一个Typescript模型作为JSON请求发送到我的后端服务器。我不能将模型更改为更工程化的格式,所以我必须使用客户端将要发送给我的格式。
Typescript接口使用管道执行多态性,如下所示:
export interface Field {
align: 'center' | 'left'; // css property that does not work disabled: boolean;
label: string;
readonly: boolean;
ref: string; // unique identifier size: string; // css width type: FIELD_TYPES;
value: string;
required: boolean;
visible: string; // 'true' | 'plugin:...'
invisible: 'true' | 'false'; // never used
optional: string; // just in 3 fields, never used
option:
| string // 'plugin:...'
| { value: string; label: string; disable?: string; labelEng?: string, valueOfAnswerInInterestType?: string }[] //FieldOption
| { 1?: string; 2?: string; 3?: string; 4?: string; 5?: string; 6?: string }; //Map<Integer,String>
}
如您所见,option
可以是String
、数组或普通POJO。
我需要实现的是创建一个JacksonMap,并使用Java强大的instanceof
操作符处理反序列化的类。
看看这个目标模型:
@Data
public class Field {
private DetFieldAlignment align; // css property that does not work disabled: boolean;
....
private String optional;// just in 3 fields, never used
private Object option; // 'plugin:...' | [{ value: 1, label: 'my value' }, ...] | { "1": "Option one ..."}
}
@Data
public class DetFieldOption {
private String value;
private String label;
private String disable;
....
}
我需要指导Jackson对Object
的可能子类进行多态序列化,但我遇到了困难。我编写了JUnit测试来验证结果(option instanceof String
vs检查列表中的每个项目是否都是instanceof FieldOption
),但显然它不起作用。
使用上面的模型,在我的测试负载中可以识别String
,但是FieldOption
数组转换为LinkedHashMap
数组
在没有处理Map<Integer,String>
的情况下,我尝试将以下多态注解添加到Object option
字段
@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
@JsonSubTypes({
@JsonSubTypes.Type(String.class),
@JsonSubTypes.Type(FieldOption.class)
})
它不起作用,但以下情况除外
Caused by: java.lang.IllegalStateException: Subtypes java.lang.String and java.lang.Object have the same signature and cannot be uniquely deduced.
at com.fasterxml.jackson.databind.jsontype.impl.AsDeductionTypeDeserializer.buildFingerprints(AsDeductionTypeDeserializer.java:89)
at com.fasterxml.jackson.databind.jsontype.impl.AsDeductionTypeDeserializer.<init>(AsDeductionTypeDeserializer.java:48)
at com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder.buildTypeDeserializer(StdTypeResolverBuilder.java:166)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findPropertyTypeDeserializer(BasicDeserializerFactory.java:2022)
... 89 more
我不能控制来自前端的有效负载,这意味着我不能要求FE开发人员在有效负载中添加类型指示,特别是考虑到对象可能是String。
问题
如何定义一个多态序列化,使其反序列化为:
- java.lang.String
- java.util.Collection
- java. util. Map〈整数,字符串〉
当然,我不希望键是整数以外的值
1条答案
按热度按时间8i9zcol21#
因为你想把一个多态值封装到
Field
类的Object
字段中,所以这个任务可以用一个定制的StdDeserializer
反序列化器来解决,它可以区分你指定的三种情况(字符串、数组和Map)。您可以定义一个自定义
stdDeserializer
,该自定义stdDeserializer
可以在您指定的三种情况下返回不同的对象,检查JsonNode
选项是字符串、数组还是对象:然后,您可以将如下所示的json字符串转换为
Field
对象: