1. 概述
本文将深入介绍 Jackson 中最常遇到的几个异常,包括:
JsonMappingException
UnrecognizedPropertyException
MismatchedInputException
- Jackson 的
NoSuchMethodError
我们还会简要讨论 Jackson 的常见解析错误,例如 "No such method"
错误。
2. JsonMappingException
: 无法构造实例
2.1 问题描述
当 Jackson 无法创建类的实例时,会抛出此异常。常见于抽象类或接口类型。
例如,下面的 Zoo
类中包含了一个抽象类 Animal
类型的字段:
public class Zoo {
public Animal animal;
public Zoo() { }
}
abstract class Animal {
public String name;
public Animal() { }
}
class Cat extends Animal {
public int lives;
public Cat() { }
}
当尝试反序列化如下 JSON 时:
{"animal":{"name":"lacy"}}
会抛出:
com.fasterxml.jackson.databind.JsonMappingException:
Can not construct instance of org.baeldung.jackson.exception.Animal
2.2 解决方案
✅ 使用 @JsonDeserialize
注解指定具体实现类:
@JsonDeserialize(as = Cat.class)
abstract class Animal {}
⚠️ 如果有多个子类,建议使用多态支持,如 @JsonTypeInfo
。
3. JsonMappingException
: 找不到合适构造器
3.1 问题描述
当目标类没有默认构造器时,Jackson 无法实例化对象,抛出异常。
例如:
public class User {
public int id;
public String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
}
反序列化 JSON:
{"id":1,"name":"John"}
会抛出:
No suitable constructor found for type [simple type, class User]
3.2 解决方案
✅ 添加默认构造器:
public User() {
}
或者使用不可变字段时,为构造器参数添加 @JsonProperty
注解:
public User(@JsonProperty("id") int id, @JsonProperty("name") String name) {
this.id = id;
this.name = name;
}
4. JsonMappingException
: 根名称不匹配
4.1 问题描述
当 JSON 根对象被包装,但目标类没有对应配置时抛出。
例如:
{"user":{"id":1,"name":"John"}}
反序列化为 User.class
时抛出:
Root name 'user' does not match expected ('User')
4.2 解决方案
✅ 使用 @JsonRootName
注解:
@JsonRootName(value = "user")
public class UserWithRoot {
public int id;
public String name;
}
同时启用 UNWRAP_ROOT_VALUE
:
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
5. JsonMappingException
: 找不到序列化器
5.1 问题描述
当类字段为 private
且没有 getter 方法时,Jackson 无法序列化对象,抛出:
No serializer found for class UserWithPrivateFields
5.2 解决方案
✅ 设置字段可见性:
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
或者使用注解:
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class UserWithPrivateFields { ... }
6. JsonMappingException
: 无法反序列化实例
6.1 问题描述
当期望反序列化为 User
实例,但输入是 List<User>
时,抛出:
Can not deserialize instance of User out of START_ARRAY token
6.2 解决方案
✅ 使用 TypeReference
反序列化为 List:
List<User> users = mapper.readValue(json, new TypeReference<List<User>>() {});
7. JsonMappingException
: 无法将对象反序列化为 String
7.1 问题描述
当 JSON 中某个字段是对象,但目标类中定义为 String
时,抛出:
Cannot deserialize value of type `java.lang.String` from Object value
例如:
{
"firstName":"Azhrioun",
"lastName":"Abderrahim",
"contact":{
"email":"[email protected]"
}
}
但目标类中 contact
是 String
类型。
7.2 解决方案
✅ 将字段改为对应对象类型:
public class Contact {
private String email;
}
public class PersonContact {
private String firstName;
private String lastName;
private Contact contact;
}
8. UnrecognizedPropertyException
8.1 问题描述
当 JSON 包含类中未定义的字段时抛出:
Unrecognized field "checked" (class User)
8.2 解决方案
✅ 配置 ObjectMapper
忽略未知字段:
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
或者使用注解:
@JsonIgnoreProperties(ignoreUnknown = true)
public class User { ... }
9. JsonParseException
: 遇到单引号
9.1 问题描述
当 JSON 使用单引号时抛出:
Unexpected character (''' (code 39)): was expecting double-quote
9.2 解决方案
✅ 启用单引号支持:
JsonFactory factory = new JsonFactory();
factory.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
ObjectMapper mapper = new ObjectMapper(factory);
10. JsonParseException
: 遇到非法字符
10.1 问题描述
JSON 中字段名未加引号、缺少逗号、格式错误等,会导致解析失败。
例如:
{"id":1, name:"John"}
抛出:
Unexpected character ('n' (code 110)): was expecting double-quote to start field name
10.2 解决方案
✅ 检查 JSON 格式,确保字段名用双引号包裹,结构正确。
11. MismatchedInputException
11.1 问题描述:无默认构造器
类没有默认构造器,反序列化失败。
11.2 解决方案
✅ 添加默认构造器 或为构造器参数加上 @JsonProperty
注解。
11.3 问题描述:反序列化数组到对象
尝试将 JSON 数组反序列化为单个对象时抛出。
例如:
[{"id":"10","title":"Harry Potter"}]
试图反序列化为 Book.class
。
11.4 解决方案
✅ **使用 TypeReference<List<Book>>
**:
List<Book> books = mapper.readValue(json, new TypeReference<List<Book>>() {});
或者去除数组结构,反序列化为单个对象。
12. Jackson NoSuchMethodError
问题描述
当 classpath 中存在多个 Jackson 版本冲突时抛出:
java.lang.NoSuchMethodError:
com.fasterxml.jackson.core.JsonParser.getValueAsString()Ljava/lang/String;
解决方案
✅ 确保依赖版本一致,排除冲突版本。
例如在 Maven 中使用 <exclusion>
排除冲突依赖。
13. 总结
本文总结了 Jackson 使用中最常见的异常类型及其原因和解决办法,包括:
异常类型 | 常见原因 | 常见解决办法 |
---|---|---|
JsonMappingException |
抽象类、无构造器、类型不匹配等 | 使用注解、添加构造器、调整类型 |
UnrecognizedPropertyException |
JSON 中存在未知字段 | 忽略未知字段或更新类结构 |
JsonParseException |
JSON 格式错误 | 检查 JSON 语法 |
MismatchedInputException |
类型不匹配、构造器缺失 | 使用 TypeReference 、添加构造器 |
NoSuchMethodError |
Jackson 版本冲突 | 统一依赖版本 |
所有示例代码可在 GitHub 上找到。
✅ 建议:使用 Jackson 时,保持依赖版本一致、合理使用注解、规范 JSON 格式,可大大减少异常发生。