使用Jackson反序列化JSON时如何处理value字段多数据类型问题
解决方案
方案1:极简实现(无需额外配置,适配任意value类型)
直接将Output类的value字段定义为Jackson的JsonNode类型,Jackson会自动适配字符串、数组、对象等所有JSON类型,后续取值时调用JsonNode内置API判断类型即可。
完整POJO代码
// 根类 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) public class MyPojo { private List<Object> links; private Integer version; private String executionState; private List<Output> outputs; // 此处省略getter、setter、无参构造方法 }
// Output类 import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.databind.JsonNode; @JsonIgnoreProperties(ignoreUnknown = true) public class Output { private String name; private JsonNode value; // 此处省略getter、setter、无参构造方法 }
使用示例
// 反序列化逻辑保持不变 MyPojo response = new ObjectMapper().readValue(jsonString, MyPojo.class); // 取值示例 for (Output output : response.getOutputs()) { switch (output.getName()) { case "identifier": case "segment": // 读取字符串类型value String strValue = output.getValue().asText(); break; case "rules": // 读取数组类型value JsonNode ruleArr = output.getValue(); JsonNode metadata = ruleArr.get(0).get("metadata"); JsonNode data = ruleArr.get(1).get("data"); // 按业务需求遍历取值即可 break; } }
方案2:强类型实现(自定义反序列化器,类型安全)
如果需要严格的类型校验,避免后续手动判断类型出错,可以自定义value字段的反序列化逻辑,适配两种类型。
完整POJO代码
// 抽象Value父类 import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @JsonDeserialize(using = ValueDeserializer.class) public abstract class Value {}
// 字符串类型Value子类 public class StringValue extends Value { private String content; public StringValue(String content) { this.content = content; } // 此处省略getter }
// 数组类型Value子类 import java.util.List; public class ArrayValue extends Value { private List<RuleItem> content; // 此处省略getter、setter public static class RuleItem { private List<MetadataField> metadata; private List<List<Object>> data; // 此处省略getter、setter } public static class MetadataField { private String ID; private String NAME; // 此处省略getter、setter } }
// 自定义反序列化器 import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; public class ValueDeserializer extends StdDeserializer<Value> { public ValueDeserializer() { super(Value.class); } @Override public Value deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode node = p.getCodec().readTree(p); if (node.isTextual()) { return new StringValue(node.asText()); } else if (node.isArray()) { return p.getCodec().treeToValue(node, ArrayValue.class); } throw new IllegalArgumentException("不支持的value类型: " + node.getNodeType()); } }
// Output类调整为 public class Output { private String name; private Value value; // 此处省略getter、setter }
使用示例
反序列化后直接通过instanceof判断Value的实际类型即可,不会出现类型转换异常。
注意事项
- 所有POJO类需要补全getter、setter和无参构造方法,也可以直接使用Lombok的
@Data注解简化代码 @JsonIgnoreProperties(ignoreUnknown = true)用于兼容JSON多余字段,避免反序列化失败
内容的提问来源于stack exchange,提问作者Edgaras
相关产品推荐
相关产品推荐

