我已经搜索和搜索过,但没有找到答案/解决方案,因此诉诸于自己问这个。
使用fastxml杰克逊2.8.7
我有一个复杂的地图,我将其传递给Angular并通过弹簧映射作为JSON字符串返回。
地图:
Map<String, List<TableModel>> tableEntryData = new LinkedHashMap<>();
它是tablemodel列表的地图。表模型是接口,它扩展到几个具体类。因此,使用tablemodel作为对象类型使我可以将从tablememodel扩展到列表的任何具体类。
我可以使用:
将其传递给角罚ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
tableEntryJSON = mapper.writeValueAsString( tableEntryData );
但是,当我试图对json进行估算时:
tableEntryData = mapper.readValue(tableEntryJSON,
new TypeReference<LinkedHashMap<String, LinkedList<TableModel>>>() {} );
我面临这个例外:
com.fasterxml.jackson.databind.jsonmappingexception :( java.lang.nullpointerexception)(通过参考链: java.util.linkedhashmap [" table_a_list"] -> java.util.linkedlist [8])
现在我的数据映射(TableenTryData)包含这样的数据:
map = { [table_a_list] = {linkedlist of tablea}的13个对象, [table_b_list] = {tableb的两个对象的linkedlist} }
table_a_list和table_b_list是地图键。Tablea和Tabelb是实现接口tablemodel的类。
JSON创建的就是这样:
{ "TABLE_A_List" : [ {
"deserializeType" : "TableA",
"amount" : 0.0, }, {
"deserializeType" : "TableA",
"amount" : 8.3, }, {
"deserializeType" : "TableA",
"amount" : 20.0, }, {
"deserializeType" : "TableA",
"amount" : 19.4, }, {
"deserializeType" : "TableA",
"amount" : 33.9, }, {
"deserializeType" : "TableA",
"amount" : 11.3, }, {
"deserializeType" : "TableA",
"amount" : 23.6, },{
"deserializeType" : "TableA",
"amount" : 2.6, },{
"deserializeType" : "TableA",
"amount" : 3.6, },{
"deserializeType" : "TableA",
"amount" : 23.0, },{
"deserializeType" : "TableA",
"amount" : 230.6, },{
"deserializeType" : "TableA",
"amount" : 23.8, },{
"deserializeType" : "TableA",
"amount" : 11.1, }, ],
"TABLE_B_List" : [ {
"deserializeType" : "TableB",
"code" : 9, }, {
"deserializeType" : "TableB",
"code" : 1, }, ] }
看起来正确。
为了正确地从接口中挑选混凝土类,我已经定义了如下的内容
tablemodel:
@JsonDeserialize(using = ModelInstanceDeserializer.class)
@JsonIgnoreProperties(ignoreUnknown = true)
public interface TableModel
{
....
}
tablea:
@JsonDeserialize(as = TableA.class)
@JsonIgnoreProperties(ignoreUnknown = true)
public class TableA implements Serializable
{
String deserializeType = "TableA"; //This is for providing type info that helps with the deserialization since JSON mapper erases type info inside Maps/Lists
//public getters for fields
}
tableb:
@JsonDeserialize(as = TableB.class)
@JsonIgnoreProperties(ignoreUnknown = true)
public class TableB implements Serializable
{
String deserializeType = "TableB"; //This is for providing type info that helps with the deserialization since JSON mapper erases type info inside Maps/Lists
//public getters for fields
}
然后,我还创建了一个Deserializer类ModelInstanceNcencedEserializer:
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class ModelInstanceDeserializer extends JsonDeserializer<TableModel> {
@Override
public TableModel deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
ObjectNode root = (ObjectNode) mapper.readTree(jp);
Class<? extends TableModel> instanceClass = null;
String type = "";
if (root.has("deserializeType")) {
type = root.get("deserializeType").asText();
}
if (type.equals("TableA")) {
instanceClass = TableA.class;
} else if (type.equals("TableA")) {
instanceClass = TableB.class;
}
if (instanceClass == null) {
return null;
}
return mapper.readValue(jp, instanceClass);
}
}
现在,当这个婴儿有些工作时,有一个问题。Deserializer读取第二映射条目是第一个地图条目的一部分列表。发生的事情是,求职者似乎一次从table_a_list json读取两个记录,结果最终包括第7个条目的table_b_list:
{
"TABLE_B_List" : [ {
"deserializeType" : "TableB",
"code" : 9,
}, {
"deserializeType" : "TableB",
"code" : 1,
}, ]
}
table_a_list中有13个条目。
,任何人都可以指出我如何正确执行此操作。我认为我需要更好地配置求职者或其他问题。
是的,我总是可以回去摆脱Tablemodel方法,使用更好的东西,但这不是重点。此时,这将需要太多的代码更改。我需要正确地做这项工作。
几分钟后发现了解决方案,尽管我的大脑失去了2天。
使用:
return mapper.readValue(root.toString(), instanceClass);
而不是:
return mapper.readValue(jp, instanceClass);
JsonParser
上的readValue
最终会增加根节点。这是一个合乎逻辑的错误 缺乏血腥指南。
感谢大家的回答!:*