如何使用Jackson按JSON类型解析对象,反序列化不同结构的data字段
实现方案
你可以通过Jackson自定义反序列化器,或者运行时判断JsonNode类型两种方式实现需求,以下是可直接运行的完整实现:
方案1:自定义反序列化器(推荐,类型处理逻辑内聚)
步骤1:定义外层响应类
给data字段指定自定义反序列化器:
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; public class RootResponse { @JsonProperty("value") private Value value; public static class Value { @JsonProperty("data") @JsonDeserialize(using = DataDeserializer.class) private Object data; @JsonProperty("isGraduated") private Boolean isGraduated; // 可添加工具方法避免业务代码强转 public boolean isDataStringList() { return data instanceof List; } public boolean isDataInfo() { return data instanceof Info; } // getter、setter省略 } // getter、setter省略 }
步骤2:编写自定义反序列化器
根据JSON节点类型自动匹配反序列化目标类:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.annotation.JsonProperty; import java.io.IOException; import java.util.List; public class DataDeserializer extends StdDeserializer<Object> { protected DataDeserializer() { super(Object.class); } @Override public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken currentToken = p.currentToken(); // 数组类型直接反序列化为字符串列表 if (currentToken == JsonToken.START_ARRAY) { return p.readValueAs(List.class); } // 对象类型先取info字段再反序列化为Info类 if (currentToken == JsonToken.START_OBJECT) { DataWrapper wrapper = p.readValueAs(DataWrapper.class); return wrapper.getInfo(); } return null; } // 适配对象2中data的嵌套结构 private static class DataWrapper { @JsonProperty("info") private Info info; // getter、setter省略 } }
步骤3:测试代码
import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; public class DeserializeTest { public static void main(String[] args) throws Exception { ObjectMapper objectMapper = new ObjectMapper(); // 测试数组类型的JSON String json1 = "{\"value\":{\"data\":[\"John\",\"Justin\",\"Tom\"],\"isGraduated\":false}}"; RootResponse res1 = objectMapper.readValue(json1, RootResponse.class); if (res1.getValue().isDataStringList()) { List<String> nameList = (List<String>) res1.getValue().getData(); System.out.println(nameList); // 输出 [John, Justin, Tom] } // 测试对象类型的JSON String json2 = "{\"value\":{\"data\":{\"info\":{\"background\":{\"primarySchool\":\"A school\",\"univeristy\":\"X univeristy\"},\"name\":\"John\",\"gender\":\"male\",\"dayOfBirth\":\"1995-04-24\"}},\"isGraduated\":false}}"; RootResponse res2 = objectMapper.readValue(json2, RootResponse.class); if (res2.getValue().isDataInfo()) { Info info = (Info) res2.getValue().getData(); System.out.println(info.getName()); // 输出 John } } }
方案2:JsonNode运行时转换(无需自定义反序列化器,代码更简洁)
如果不想写反序列化器,可以直接将data字段声明为JsonNode类型,业务代码中手动判断类型转换:
// Value类中data字段定义 @JsonProperty("data") private JsonNode data; // 业务代码中转换 ObjectMapper objectMapper = new ObjectMapper(); if (data.isArray()) { List<String> nameList = objectMapper.convertValue(data, new TypeReference<List<String>>() {}); } else if (data.isObject()) { Info info = objectMapper.convertValue(data.get("info"), Info.class); }
内容的提问来源于stack exchange,提问作者Blind
相关产品推荐
相关产品推荐

