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: Can not deserialize of java.util.ArrayList out of instance of >START_OBJECT token [Source: 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;
}
上記の説明が明確でない場合は、お詫び申し上げます。ジャクソンにはこれを達成する方法が必要だと思いますが、それを理解することはできません. 誰かが何かアイデアを持っているか、正しい方向に私を向けることができれば、それは大歓迎です。
ありがとう、ダーム