Contents

Jackson 反序列化Snake命名到Camel命名

1. 概述

JSON 对象中的字段名称可以采用多种格式。当我们想要将它们加载到 POJO 中时,我们可能会遇到 Java 代码中的属性名称与 JSON 中的命名约定不匹配的问题。

2. 安装Jackson

让我们首先将Jackson 依赖项 添加到我们的pom.xml文件中:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13</version>
</dependency>

3. 使用默认反序列化

让我们考虑一个示例User类:

public class User {
    private String firstName;
    private String lastName;
    // standard getters and setters
}

让我们尝试加载此 JSON,它使用 Snake Case 命名标准(小写名称由*_*分隔):

{
    "first_name": "Jackie",
    "last_name": "Chan"
}

首先,我们需要使用ObjectMapper反序列化这个 JSON:

ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(JSON, User.class);

然而,当我们尝试这样做时,我们得到一个错误:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "first_name" (class com.blogdemo.jackson.snakecase.User), not marked as ignorable (2 known properties: "lastName", "firstName"])

不幸的是,Jackson 无法将 JSON 中的名称与User 中的字段名称完全匹配。 接下来,我们将学习三种方法来解决这个问题。

4. 使用*@JsonProperty*注解

我们可以在类的字段上使用*@JsonProperty*注解将字段映射到 JSON 中的确切名称:

public class UserWithPropertyNames {
    @JsonProperty("first_name")
    private String firstName;
    
    @JsonProperty("last_name")
    private String lastName;
    // standard getters and setters
}

现在我们可以将 JSON 反序列化为UserWithPropertyNames

ObjectMapper objectMapper = new ObjectMapper();
UserWithPropertyNames user = objectMapper.readValue(JSON, UserWithPropertyNames.class);
assertEquals("Jackie", user.getFirstName());
assertEquals("Chan", user.getLastName());

5. 使用*@JsonNaming*注解

接下来,我们可以在类上使用*@JsonNaming注解,*所有字段将使用 snake case 反序列化

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class UserWithSnakeStrategy {
    private String firstName;
    private String lastName;
    // standard getters and setters
}

然后再次反序列化我们的 JSON:

ObjectMapper objectMapper = new ObjectMapper();
UserWithSnakeStrategy user = objectMapper.readValue(JSON, UserWithSnakeStrategy.class);
assertEquals("Jackie", user.getFirstName());
assertEquals("Chan", user.getLastName());

6. 配置ObjectMapper

最后,我们可以使用ObjectMapper上的setPropertyNamingStrategy方法为所有序列化配置它:

ObjectMapper objectMapper = new ObjectMapper()
  .setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
User user = objectMapper.readValue(JSON, User.class);
assertEquals("Jackie", user.getFirstName());
assertEquals("Chan", user.getLastName());

如我们所见,我们现在可以将 JSON 反序列化为原始User对象,即使User类没有任何注解。

我们应该注意到还有其他命名约定(例如 kebab 大小写),并且上述解决方案也适用于它们。