我正在使用 Jackson 将 JSON 字符串反序列化为对象。我有一个类似于下面的对象
@Data
public class Party {
protected String partyType;
protected List<Field> fields;
}
为了反序列化这个派对对象,我有一个 mixin 类,它的工作原理如下
@JsonIgnoreProperties(ignoreUnknown = true)
abstract class PartyMixin {
@JsonCreator
PartyMixin(@JsonProperty("partyType") String partyType) {}
@JsonProperty("fields")
@JsonDeserialize(using=FieldListDeserializer.class) List<Field> fields;
private static final class FieldListDeserializer extends JsonDeserializer<List<Field>> {
public List<Field> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return DeserializationUtils.deserializeFromDataNode(jp, ctxt, "field", new TypeReference<List<Field>>() {});
}
}
}
deserializeFromDataNode 方法看起来像
public static <T> T deserializeFromDataNode(JsonParser jp, DeserializationContext ctxt, String propertyName, TypeReference<T> typeReference) throws IOException, JsonProcessingException {
if (jp.hasCurrentToken() && jp.getCurrentToken().equals(JsonToken.START_OBJECT)) {
JsonNode dataNode = jp.readValueAs(JsonNode.class);
if (dataNode.has(propertyName)) {
return OBJECT_MAPPER.reader(typeReference).<T>readValue(dataNode.get(propertyName));
}
return null;
}
throw ctxt.mappingException("Expected JSON object");
}
这一切工作正常,arrayList 被反序列化为正确对象的正确列表。但是,我遇到困难的地方是在以下情况下,我有一个各方列表,每个人都有一个字段列表
@Data
public class Event {
protected Integer eventId;
protected List<Party> parties;
}
在这种情况下,我在反序列化上述各方时遇到错误。
@JsonProperty("parties")
@JsonDeserialize(using=PartyListDeserializer.class) List<Party> parties;
private static final class PartyListDeserializer extends JsonDeserializer<List<Party>> {
public List<Party> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return DeserializationUtils.deserializeFromDataNode(jp, ctxt, "party", new TypeReference<List<Party>>() {});
}
}
错误是
java.lang.IllegalArgumentException:无法从>START_OBJECT 标记中反序列化 java.util.ArrayList 的实例 [来源:N/A;行:-1,列:-1](通过参考链:
我明白了我收到错误的原因 - 当我反序列化对象数组时,它不希望嵌套对象之一包含数组。这是我被困在一个整洁的可重用方式来遍历 JSON 和反序列化常规对象和数组对象的地方。创建泛型方法的主要障碍是如何知道嵌套数组的类型。所以在我上面的第一个数组的方法中,我将类型传递给阅读器。如果我将方法更改为递归并检查节点是否为数组,那么如何从节点推断类型和名称?
if (dataNode.has(propertyName)) {
for(JsonNode subNode: dataNode) {
if (subNode.isArray()) {
// How to know the type and name from the node to pass it in?
List<T> subActions = deserializeFromDataNode(jp, ctxt...
}
else {
T value = OBJECT_MAPPER.reader(typeReference).readValue(subNode);
actions.add(value);
}
}
return (T) actions;
}
抱歉,如果我上面的解释不是那么清楚。我认为杰克逊必须有一种方法来实现这一点,但就是想不通。如果有人有任何想法或可以指出我正确的方向,将不胜感激。
谢谢, 真皮