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]"
  }
}

但目标类中 contactString 类型。

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 格式,可大大减少异常发生。


原始标题:Jackson Exceptions - Problems and Solutions

« 上一篇: Baeldung每周评论50
» 下一篇: Baeldung 周评51