使用 jackson 在 java 中嵌套自定义反序列化



我一直想知道如何正确解决这个问题

我有一个这样的数据模型:

Class B
String fieldB1;
String fieldB2;
Class A
String fieldA1;
String fieldA2;
List<B> fieldA3;

(然后是另一个第三个类,它与另一个具有字段和 A 对象列表的层次结构相同,但为了简单起见,让我们坚持使用 A 和 B)

现在在另一方面,我必须在具有相同名称和参数的类中反序列化这些类,只是具有不同的数据类型

所以^必须读作:

Class B
int fieldB1;
double fieldB2;
Class A
float fieldA1;
float fieldA2;
List<B> fieldA3;

由于我没有经验,我的第一个猜测是在 jackson 中为 A 和 B 编写 custom 解串器,当我反序列化像 B 这样的类时,它没有引用其他具有自定义反序列化方法的类,转换很容易。

但是,如何为 A 类创建自定义反序列化程序呢?当我必须反序列化 fieldA3(也就是 B 对象列表)时,我应该如何操作?是否应该尝试以某种方式在 ClassACustomDeserializer 中调用 ClassBCustomDeserializer?怎么做? 或者有没有另一种更简单的解决方案来告诉杰克逊根据我的个人映射将一些字符串字段转换为其他类型的字符串字段?

这就是我反序列化 B 的方式

public class BDeserializer extends StdDeserializer<B> { 
public BDeserializer() { 
this(null); 
} 
public BDeserializer(Class<?> vc) { 
super(vc); 
}
@Override
public B deserialize(JsonParser jp, DeserializationContext ctxt) 
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
int fieldB1= node.findValue("fieldB1").asInt();
double fieldB2= node.findValue("fieldB2").asDouble();
return new B(fieldB1,fieldB2);
}
}

> Jackson 足够聪明,可以将文本值转换为适当的数字类型,因此它应该能够反序列化 JSON,如下所示:

{ "fieldB1": 10, "fieldB2" : "0.333" }

到您的

Class B
int fieldB1;
double fieldB2;

很好,即使没有使用自定义反序列化程序。

如果您想坚持使用自定义反序列化程序,无论出于何种原因, 您可以使用 JsonNode.traverse() 创建一个子解析器:

JsonParser parser = node.findValue("fieldA3").traverse();
parser.setCodec(jp.getCodec());
List<B> list = parser.readValueAs(new TypeReference<List<B>>() {});

或自己导航令牌流,而不是使用find

while(jp.nextToken() != JsonToken.END_OBJECT) {
if(jp.currentToken() == JsonToken.FIELD_NAME) {
switch (jp.getCurrentName()) {
//...
case "fieldA3":
jp.nextToken();
list=jp.readValueAs(new TypeReference<List<ClassB>>() {}));
break;
}
}
}

如果性能问题,后者应该更有效率。

最新更新