【发布时间】:2017-08-08 21:36:42
【问题描述】:
我被一些杰克逊多态问题所困扰。
我从事网络 JDR 角色编辑器个人项目。我使用 Springboot 并尝试坚持哲学。此外,我尝试制作一些独立的包,因为我的实际工作(另一个 springboot 项目)的研究案例。
没有 Jackson 配置,我对 Competence 的序列化没有任何问题。但是当我尝试取回对网络编辑器的任何修改时,因此当 Jackson 对 Competence 进行反序列化时,“依赖”属性会出现问题。
这是我的课程:
我尝试序列化/反序列化的那个:
public class Competence 实现 Composante, ComposanteTemplate {
公共枚举类别{
学徒,
比较
}
私有字符串 nom;
私有字符串描述;
私人类别类别;
私人礼拜堂;
私有属性模板依赖;
私有列表 sousCompetences = new ArrayList();
公共字符串 getNom() {
返回名称;
}
公共无效setNom(字符串标称){
this.nom = 标称;
}
公共字符串 getDescription() {
返回说明;
}
公共无效 setDescription(字符串描述){
this.description = 描述;
}
公共能力 getTemplate() {
返回这个;
}
公共类别 getCategorie() {
返回类别;
}
公共无效setCategorie(类别类别){
this.categorie = 类别;
}
公共Chapitre getChapitre(){
返回章节;
}
公共无效setChapitre(Chapitre chapitre){
this.chapitre = chapitre;
}
公共属性模板 getDependance() {
返回依赖;
}
公共无效setDependance(属性模板依赖){
this.dependance = 依赖;
}
公共列表 getSousCompetences() {
返回sousCompetences;
}
公共无效 setSousCompetences(列出 sousCompetences){
this.sousCompetences = sousCompetences;
}
公共布尔 isOuverte() {
返回 !sousCompetences.isEmpty();
}
}
我有问题的属性的超类:
公共接口 AttributTemplate 扩展 ComposanteTemplate {}
可用于 Competence#dependance 属性的两个子类:
公共枚举 Carac 实现 AttributTemplate, Attribut {
堡垒(Type.PHYSIQUE),
敏捷(Type.PHYSIQUE),
抗性(类型.物理),
OBSERVATEUR(Type.PHYSIQUE),
SAVANT(Type.MENTALE),
诡计(类型.MENTALE),
TALENTUEUX(Type.MENTALE),
CHARMEUR(Type.MENTALE);
公共枚举类型{
体质,
心理
}
公共最终类型类型;
public final String nom = name().toLowerCase();
私有字符串描述;
Carac(类型类型){
this.type = 类型;
}
@Override
public String getNom() { return nom; }
@Override
public String getDescription() { 返回描述; }
@Override
public Carac getTemplate() { return this; }
public void setDescription(String description) { this.description = description; }
}
公共枚举 ArtTemplate 实现 AttributTemplate {
ART_GUERRIER(2, 1),
ART_ETRANGE(1, 2),
ART_GUILDIEN(1, 1);
公共静态最终字符串 ART_PREFIX = "ART";
public final String nom = name().toLowerCase().replace("_", "");
public final int nbCaracsPhysiques;
public final int nbCaracsMentales;
私有字符串描述;
ArtTemplate(int nbCaracsPhysiques,int nbCaracsMentales){
this.nbCaracsMentales = nbCaracsMentales;
this.nbCaracsPhysiques = nbCaracsPhysiques;
}
@Override
公共字符串 getNom() {
返回名称;
}
@Override
公共字符串 getDescription() {
返回说明;
}
公共无效 setDescription(字符串描述){
this.description = 描述;
}
公共 int getNbCaracs() {
返回 nbCaracsPhysiques + nbCaracsMentales;
}
}
结果 json(然后是我发送的 json)是:
{"nom":"Comp_1489746646510","description":"ezbuixnwrclfvmgwdviubcauenzytpzzvumnohwyhpuynxaqhkjdbqygtrmbtlschthovuyoioolkaucwokkfjnaujnufshrjboykuqce","categorie":"APPRENTI","chapitre":"GUERRE","ouvertance":"falseART":" "sousCompetences":[]}
问题: 我知道我的问题是由抽象关系 AttributTemplate 引起的,然后当 Jackson 尝试反序列化时,他不知道要使用 Carac 或 ArtTemplate 类中的哪个。 我尽量保持 Competence 不变(Competence 来自外部 jar),因此无法对此类进行注释。
我已经尝试了许多我找到的解决方案 (Jackson 1.5: Polymorphic Type Handling, first steps),唯一有效的是定义一个 DeserializationProblemHandler
mapper.addHandler(new DeserializationProblemHandler() {
@Override
public Object handleMissingInstantiator(DeserializationContext ctxt, Class<?> instClass, JsonParser p, String msg) throws IOException {
if (instClass == AttributTemplate.class) {
String name = p.getText();
return !name.startsWith(ArtTemplate.ART_PREFIX) ? Carac.valueOf(name) : ArtTemplate.valueOf(name);
}
return super.handleMissingInstantiator(ctxt, instClass, p, msg);
}
});
但我对这个解决方案感觉不好,因为我确信还有另一个漂亮的解决方案。
那么是否可以配置映射器,以便他能够确定必须使用 Carac 或 ArtTemplate 中的哪一个来获取 AttributTemplate?
编辑: 我设法得到了这个:
{"nom":"Comp_1489756873433","description":"kruzueemlwisibshlkotasayfkhdqkqolvhlqgsnntndkpvbmmgklqysabiakaolempmupeyiqaztdcrhwimdksgzybbdzttwnwqjxhfo","categorie":"COMPAGNON","chapitre":"GUERRE.persoged. Carac","AGILE"],"ouverte":true,"sousCompetences":[...]}
通过像这样配置映射器
抽象类 CompetenceMixIn { 私有属性模板依赖; @JsonTypeInfo(使用=JsonTypeInfo.Id.CLASS,包括=JsonTypeInfo.As.EXISTING_PROPERTY,属性=“依赖”) @JsonSubTypes({ @JsonSubTypes.Type(value = Carac.class, name = "carac"), @JsonSubTypes.Type(value = ArtTemplate.class, name = "artTemplate") }) 公共无效setDependance(属性模板依赖){ this.dependance = 依赖; } }ObjectMapper 映射器 = jsonConverter.getObjectMapper(); mapper.addMixIn(Competence.class, CompetenceMixIn.class);
如您所见,我仍然被包裹dependance 值的数组所寄生。我会(...)"dependance": "AGILE", (...) 而不是(...)"dependance":["mova.ged.perso.inne.Carac", "AGILE"], (...)
而且我不知道要改变什么才能拥有它。
【问题讨论】:
-
我之前回答过类似的问题。杰克逊允许这是可配置的。我不想为你的具体情况重新发明这个,所以请看这里:stackoverflow.com/questions/38501574/… 那里的例子很简单。 Params 类有 2 个实现,我告诉杰克逊使用什么属性来查找如何反序列化它
-
我尝试了您的示例,但仍然找不到真正的解决方案。感谢您,我在找到解决方案的开头修改了我的帖子。
-
仍然有问题....我无法想象在我看来如此简单的事情会有这样的问题??
标签: java spring-boot jackson polymorphism json-deserialization