使用Jackson将含List<Map<String,String>>的JSON反序列化为自定义对象遇错
Jackson反序列化MyCustomObject的注解解决方案
常见问题及对应注解修复
1. 属性名与JSON字段不匹配
如果Java对象的属性名和JSON里的字段名对不上(比如Java里是userName,JSON里是user_name),直接用@JsonProperty指定映射关系:
public class MyCustomObject { @JsonProperty("user_name") private String userName; // 其他属性... }
2. 嵌套对象反序列化异常
如果你的对象里包含自定义嵌套对象,要确保嵌套对象也配置好Jackson规则:
- 嵌套对象如果只有带参构造器,必须给构造器加
@JsonCreator,同时每个参数用@JsonProperty标记对应JSON字段:
public class MyCustomObject { private NestedObject nested; public static class NestedObject { private String nestedField; @JsonCreator public NestedObject(@JsonProperty("nested_field") String nestedField) { this.nestedField = nestedField; } } }
- 嵌套对象最好加上
@JsonIgnoreProperties(ignoreUnknown = true),避免JSON里有多余字段导致报错。
3. List<Map<String,String>>类型属性处理
这个类型Jackson默认就能处理,但要注意两个点:
- 如果JSON里的字段名和Java属性名不一致,用
@JsonProperty指定,比如:
@JsonProperty("data_list") private List<Map<String,String>> dataList;
- 如果该字段可能为
null或者在某些JSON里不存在,给属性加@JsonProperty(required = false),或者在类上全局加@JsonIgnoreProperties(ignoreUnknown = true)忽略未知字段。
4. 缺少无参构造器
Jackson默认需要类有无参构造器,如果你的MyCustomObject只有带参构造器,要么补一个无参构造器,要么给带参构造器加@JsonCreator+@JsonProperty:
public class MyCustomObject { private String name; private List<Map<String,String>> data; // 推荐:补无参构造器 public MyCustomObject() {} // 备选:带参构造器加注解 @JsonCreator public MyCustomObject(@JsonProperty("name") String name, @JsonProperty("data") List<Map<String,String>> data) { this.name = name; this.data = data; } }
5. JSON存在未知字段
如果JSON里有MyCustomObject没定义的字段,会直接触发MismatchedInputException,在类上加@JsonIgnoreProperties(ignoreUnknown = true)就能忽略这些多余字段:
@JsonIgnoreProperties(ignoreUnknown = true) public class MyCustomObject { // 属性定义... }
完整可运行示例
自定义对象MyCustomObject
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; import java.util.Map; @JsonIgnoreProperties(ignoreUnknown = true) public class MyCustomObject { private String id; private NestedInfo nestedInfo; private List<Map<String, String>> detailList; // 无参构造器必须有 public MyCustomObject() {} // 可选:带参构造器(方便初始化,反序列化也能用) @JsonCreator public MyCustomObject( @JsonProperty("id") String id, @JsonProperty("nested_info") NestedInfo nestedInfo, @JsonProperty("detail_list") List<Map<String, String>> detailList) { this.id = id; this.nestedInfo = nestedInfo; this.detailList = detailList; } // Getter/Setter必须有,Jackson需要通过这些访问属性 public String getId() { return id; } public void setId(String id) { this.id = id; } public NestedInfo getNestedInfo() { return nestedInfo; } public void setNestedInfo(NestedInfo nestedInfo) { this.nestedInfo = nestedInfo; } public List<Map<String, String>> getDetailList() { return detailList; } public void setDetailList(List<Map<String, String>> detailList) { this.detailList = detailList; } // 嵌套内部类 @JsonIgnoreProperties(ignoreUnknown = true) public static class NestedInfo { private String name; private Integer age; public NestedInfo() {} @JsonCreator public NestedInfo(@JsonProperty("name") String name, @JsonProperty("age") Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } } }
反序列化测试代码
import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; public class DeserializeTest { public static void main(String[] args) throws IOException { ObjectMapper objectMapper = new ObjectMapper(); // 示例JSON(适配上面的对象结构) String json = "{\n" + " \"id\": \"123\",\n" + " \"nested_info\": {\n" + " \"name\": \"张三\",\n" + " \"age\": 25\n" + " },\n" + " \"detail_list\": [\n" + " {\"key1\": \"value1\"},\n" + " {\"key2\": \"value2\"}\n" + " ]\n" + "}"; MyCustomObject obj = objectMapper.readValue(json, MyCustomObject.class); System.out.println(obj.getId()); System.out.println(obj.getNestedInfo().getName()); System.out.println(obj.getDetailList().get(0).get("key1")); } }
适配多结构JSON的额外技巧
如果你的三种JSON响应结构有差异(比如字段名多变、字段可选),可以用这些注解:
@JsonAlias({"field1", "field2"}):给属性指定多个别名,适配不同JSON里的不同字段名,比如:@JsonAlias({"detail_list", "details"}) private List<Map<String,String>> detailList;@JsonProperty(required = false):标记属性非必填,避免某些JSON里缺少该字段时报错。
内容的提问来源于stack exchange,提问作者Nayrb
相关产品推荐
相关产品推荐

