我一直想知道如何正确解决这个问题
我有这样的数据模型:
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编写海关Deserializer,当我反序列化类似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);
}
}
答案 0 :(得分:2)
杰克逊非常聪明,可以将文本值转换为适当的数字类型,因此它应该能够反序列化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;
}
}
}
如果表现令人担忧,后者应该更有效率。