如何用Jackson/ObjectMapper将特定JSON反序列化为Java对象?
使用Jackson实现动态Key的JSON反序列化
核心思路
你的需求本质是要把JSON中以key/value形式存储的属性,映射到Java类的对应字段上,同时区分不同的对象类型(Account/User)。解决方案是自定义Jackson反序列化器,通过解析attribute数组构建键值对,再根据键判断目标对象类型,最终完成映射。
步骤1:调整并完善Java类定义
给Response的items字段添加反序列化注解,指定自定义的反序列化器;保留你原有的Header、Account、User类:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import java.util.List; public class Response { private Header header; // 指定自定义反序列化器处理items字段 @JsonDeserialize(using = ItemListDeserializer.class) private List<Object> items; // getters and setters } public class Header { private String transactionId; private String application; // getters and setters } public class Account { private String accountType; private String accountId; // getters and setters } public class User { private String userType; private String userId; // getters and setters }
步骤2:编写自定义反序列化器
创建ItemListDeserializer类,继承JsonDeserializer<List<Object>>,实现自定义解析逻辑:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class ItemListDeserializer extends JsonDeserializer<List<Object>> { private final ObjectMapper objectMapper = new ObjectMapper(); @Override public List<Object> deserialize(JsonParser parser, DeserializationContext context) throws IOException { List<Object> resultList = new ArrayList<>(); JsonNode rootNode = parser.getCodec().readTree(parser); // 读取items下的item数组 JsonNode itemArrayNode = rootNode.get("item"); for (JsonNode itemNode : itemArrayNode) { // 解析当前item的attribute数组,转为键值对Map JsonNode attributeArrayNode = itemNode.get("attributes").get("attribute"); Map<String, String> attrMap = new HashMap<>(); for (JsonNode attrNode : attributeArrayNode) { String key = attrNode.get("key").asText(); String value = attrNode.get("value").asText(); attrMap.put(key, value); } // 根据Map中的key判断目标对象类型 Object targetObj; if (attrMap.containsKey("accountType")) { targetObj = objectMapper.convertValue(attrMap, Account.class); } else if (attrMap.containsKey("userType")) { targetObj = objectMapper.convertValue(attrMap, User.class); } else { // 处理未知类型,可根据需求调整 targetObj = attrMap; } resultList.add(targetObj); } return resultList; } }
步骤3:执行反序列化测试
使用ObjectMapper完成反序列化操作:
import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; public class DeserializeTest { public static void main(String[] args) throws IOException { String jsonStr = "{\n" + " \"header\": {\n" + " \"transactionId\": \"12345\",\n" + " \"application\": \"testApp\"\n" + " },\n" + " \"items\": {\n" + " \"item\": [\n" + " {\n" + " \"attributes\": {\n" + " \"attribute\": [\n" + " {\n" + " \"key\": \"accountType\",\n" + " \"value\": \"TYPE1\"\n" + " },\n" + " {\n" + " \"key\": \"accountId\",\n" + " \"value\": \"123\"\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " {\n" + " \"attributes\": {\n" + " \"attribute\": [\n" + " {\n" + " \"key\": \"userType\",\n" + " \"value\": \"TYPE2\"\n" + " },\n" + " {\n" + " \"key\": \"userId\",\n" + " \"value\": \"321\"\n" + " }\n" + " ]\n" + " }\n" + " }\n" + " ]\n" + " }\n" + "}"; ObjectMapper mapper = new ObjectMapper(); Response response = mapper.readValue(jsonStr, Response.class); // 验证结果 System.out.println("Header TransactionId: " + response.getHeader().getTransactionId()); for (Object item : response.getItems()) { if (item instanceof Account) { Account account = (Account) item; System.out.println("Account Type: " + account.getAccountType() + ", ID: " + account.getAccountId()); } else if (item instanceof User) { User user = (User) item; System.out.println("User Type: " + user.getUserType() + ", ID: " + user.getUserId()); } } } }
关键说明
- 自定义反序列化器负责解析JSON中嵌套的
attribute结构,将key/value转为Map,再通过Jackson的convertValue方法自动映射到目标Java类。 - 通过判断Map中的特征key(如
accountType、userType)来区分要实例化的对象类型,可根据实际需求扩展更多类型判断逻辑。 - 确保所有Java类都有完整的getter/setter方法,Jackson需要通过这些方法完成字段赋值。
内容的提问来源于stack exchange,提问作者ogok
相关产品推荐
相关产品推荐

