如何用Jackson ObjectMapper反序列化含随机整数KEY的JSON?
问题描述
给定JSON响应:
{ "profile": { "userData": { "338282892": [ { "userIdentifier": "98shdub777hsjjsuj23", "detail": "Test User DEV", "type": "customer" } ] } } }
创建UserProfileModel.java后执行反序列化代码:
UserProfileModel model = objectMapper.readValue(body, UserProfileModel.class);
抛出异常:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "338282892"
尝试使用Map<String, List<UserPropertiesModel>>仍有问题,希望反序列化后能直接调用object.getUserIdentifier()或object.getType()方法。
解决方案
方案1:用@JsonAnySetter处理动态键
通过@JsonAnySetter注解捕获动态键值,封装直接获取用户属性的方法:
1. 定义基础属性类
public class UserPropertiesModel { private String userIdentifier; private String detail; private String type; // Getters & Setters public String getUserIdentifier() { return userIdentifier; } public void setUserIdentifier(String userIdentifier) { this.userIdentifier = userIdentifier; } public String getDetail() { return detail; } public void setDetail(String detail) { this.detail = detail; } public String getType() { return type; } public void setType(String type) { this.type = type; } }
2. 处理动态键的UserData类
public class UserData { private List<UserPropertiesModel> userProps; @JsonAnySetter public void captureDynamicKey(String key, List<UserPropertiesModel> value) { // 假设动态键对应列表仅含一个元素,直接存储 if (value != null && !value.isEmpty()) { this.userProps = value; } } // 封装直接获取目标属性的方法 public String getUserIdentifier() { return userProps != null && !userProps.isEmpty() ? userProps.get(0).getUserIdentifier() : null; } public String getType() { return userProps != null && !userProps.isEmpty() ? userProps.get(0).getType() : null; } // 如需获取完整属性对象,可添加此方法 public UserPropertiesModel getUserProperties() { return userProps != null && !userProps.isEmpty() ? userProps.get(0) : null; } }
3. 上层模型类
public class Profile { private UserData userData; // Getter & Setter public UserData getUserData() { return userData; } public void setUserData(UserData userData) { this.userData = userData; } } public class UserProfileModel { private Profile profile; // Getter & Setter public Profile getProfile() { return profile; } public void setProfile(Profile profile) { this.profile = profile; } }
使用方式
UserProfileModel model = objectMapper.readValue(body, UserProfileModel.class); String userId = model.getProfile().getUserData().getUserIdentifier(); String userType = model.getProfile().getUserData().getType();
方案2:直接用Map存储并封装快捷方法
将userData定义为Map,在模型类中封装获取属性的快捷方法:
修改Profile类
public class Profile { private Map<String, List<UserPropertiesModel>> userData; // 封装快捷方法 public String getUserIdentifier() { if (userData == null || userData.isEmpty()) return null; List<UserPropertiesModel> propsList = userData.values().iterator().next(); return propsList.isEmpty() ? null : propsList.get(0).getUserIdentifier(); } public String getType() { if (userData == null || userData.isEmpty()) return null; List<UserPropertiesModel> propsList = userData.values().iterator().next(); return propsList.isEmpty() ? null : propsList.get(0).getType(); } // Getter & Setter for userData(如需直接操作Map可保留) public Map<String, List<UserPropertiesModel>> getUserData() { return userData; } public void setUserData(Map<String, List<UserPropertiesModel>> userData) { this.userData = userData; } }
使用方式
UserProfileModel model = objectMapper.readValue(body, UserProfileModel.class); String userId = model.getProfile().getUserIdentifier(); String userType = model.getProfile().getType();
注意事项
- 若动态键对应的列表可能包含多个元素,需根据业务逻辑调整获取逻辑(比如返回列表或遍历处理)。
- 无需额外配置
FAIL_ON_UNKNOWN_PROPERTIES为false,上述方案已处理动态键的反序列化。
内容的提问来源于stack exchange,提问作者horizon
相关产品推荐
相关产品推荐

