【发布时间】:2017-03-10 08:55:12
【问题描述】:
我已经搜索和搜索,但没有找到答案/解决方案,所以我自己问这个。
使用fastxml jackson 2.8.7
我有一个复杂的映射,我将它传递给 angular,然后通过 Spring 映射作为 JSON 字符串返回。
地图:
Map<String, List<TableModel>> tableEntryData = new LinkedHashMap<>();
它是 TableModel 列表的映射。表模型是一个接口,可以扩展到几个具体的类。因此,使用 TableModel 作为对象类型允许我将任何从 TableModel 扩展的具体类放入 List。
我可以使用以下方法将其传递给 Angular Fine:
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)包含这样的数据:
地图 = { [Table_A_List] = {TableA 的 13 个对象的 LinkedList}, [Table_B_List] = {TableB 的 2 个对象的 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, }, ] }
这似乎是正确的。
为了从接口正确反序列化具体类,我定义如下
表格模型:
@JsonDeserialize(using = ModelInstanceDeserializer.class)
@JsonIgnoreProperties(ignoreUnknown = true)
public interface TableModel
{
....
}
表A:
@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
}
表B:
@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
}
然后我也创建了一个反序列化器类 ModelInstanceDeserializer:
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);
}
}
现在虽然这个婴儿有点工作,但有一个问题。反序列化器将 第二个映射条目 读取为一个列表,该列表是第一个映射条目的一部分。正在发生的事情是,反序列化器似乎一次从 TABLE_A_List JSON 读取两条记录,结果在第 7 个条目中包含 TABLE_B_List:
{
"TABLE_B_List" : [ {
"deserializeType" : "TableB",
"code" : 9,
}, {
"deserializeType" : "TableB",
"code" : 1,
}, ]
}
TABLE_A_List 共有 13 个条目。
所以任何人都可以指出我如何正确地做到这一点。我想我需要更好地配置反序列化器或其他问题。
是的,我总是可以返回并摆脱 TableModel 方法并使用更好的方法,但这不是重点。此时需要进行太多代码更改。我需要让这项工作正常进行。
【问题讨论】:
标签: json serialization jackson deserialization objectmapper