在 Java 中使用 Jackson 更改 JSON 字段名称

Jackson 是一个非常常见的库,用于在基于 Java 和 Spring Boot 的项目中处理 JSON 和序列化/反序列化。

Jackson 通过将它们原样映射到 JSON 来处理属性名称——所以 propertyName 在一个 POJO 中会有对应的 propertyName 在 JSON 中。 将 JSON 转换为 POJO 时也遵循此约定,如果名称不匹配,则无法完成转换。

但是,在许多情况下,您希望序列化的 JSON 属性具有不同的名称,例如标准化其他服务的命名约定(使用类似 snake_case, 代替 CamelCase) 或冲突的属性名称 (a Customer 可以有一个 firstName,就像一个 Agent – 一份报告可能同时包含他们的 firstName 属性,需要序列化)。

让我们创建一个 Book 类,有几个简单的字段:

public class Book {
    private String title;
    private String author;
    private int releaseYear;
    
    public Book() {}
    public Book(String title, String author, int releaseYear) {
        this.title = title;
        this.author = author;
        this.releaseYear = releaseYear;
    }
    
}

使用 Jackson 更改 JSON 字段名称

当通常转换一个实例时 Book 到 JSON 中,我们将对象的值写为 JSON 字符串,使用 ObjectMapper:

ObjectMapper mapper = new ObjectMapper();
Book book = new Book("Our Mathematical Universe", "Max Tegmark", 2014);
        
String jsonBook = mapper.writeValueAsString(book);
System.out.println(jsonBook);

结果是:

{"title":"Our Mathematical Universe","author":"Max Tegmark","releaseYear":2014}

title, authorreleaseYear 是一对一的映射到 title, authorreleaseYear POJO 的字段。 要更改 JSON 属性的名称并在序列化后保留它,无需更改您的 POJO! 用注释相关字段就足够了 @JsonProperty,并提供 JSON 名称:

public class Book {
    @JsonProperty("book_title")
    private String title;
    @JsonProperty("book_author")
    private String author;
    @JsonProperty("book_release_year")
    private int releaseYear;
    
    public Book(){}
    public Book(String title, String author, int releaseYear) {
        this.title = title;
        this.author = author;
        this.releaseYear = releaseYear;
    }
    
}

现在,当我们实例化对象并将其转换为 JSON 时:

ObjectMapper mapper = new ObjectMapper();
Book book = new Book("Our Mathematical Universe", "Max Tegmark", 2014);

String jsonBook = mapper.writeValueAsString(book);
System.out.println(jsonBook);

代码导致:

{"book_title":"Our Mathematical Universe","book_author":"Max Tegmark","book_release_year":2014}

在 JSON 到 POJO 转换中更改 JSON 字段名称?

值得注意的是,更名并不是片面的。 相同的注释可以双向工作,并且可以将具有不同名称的传入 JSON 桥接到有效对象中。 例如,代表一本书的 JSON book_title,不会映射到 title 的财产 Book 默认为类,因为它们不一样。

既然我们已经注释了 title as book_title - 转换工作得很好:

Book bookReconstructed = mapper.readValue(jsonBook, Book.class);
System.out.print(bookReconstructed);

结果是:

Book{title='Our Mathematical Universe', author='Max Tegmark', releaseYear=2014}

请注意: 要从 JSON 构造对象,您的类还需要有一个空的构造函数。 Jackson 首先实例化空对象,然后使用 getter 和 setter 填充字段。

使用 @JsonProperty 注释 Getter 和 Setter

您想为序列化和反序列化编码不同的名称吗? 例如,您可以序列化 Book 成一个 JSON bt 表示书名,但使用 JSON book_title. 您可以自定义 getter 和 setter Book 上课 @JsonProperty 注释:

@JsonProperty("bt")
public String getBt() {
    return title;
}

@JsonProperty("book_title")
public void setTitle(String title) {
    this.title = title;
}

这样,在序列化时, getBt() 方法将序列化 title 作为一个 bt JSON 中的字段。 从 JSON 读取(反序列化)时,您需要提供 book_title, 被映射到 title.

查看我们的 Git 学习实践指南,其中包含最佳实践、行业认可的标准以及随附的备忘单。 停止谷歌搜索 Git 命令,实际上 学习 它!

请注意: 以上皆是 btbook_title 将被映射到 title 场,但这并不能使 btbook_title 可互换。 如果没有先转换为,杰克逊将无法在它们之间转换 title.

现在,您可以实例化一本书,将其序列化,然后将另一个字符串反序列化为一本书:

ObjectMapper mapper = new ObjectMapper();
Book book = new Book("Our Mathematical Universe", "Max Tegmark", 2014);


String jsonBook = mapper.writeValueAsString(book);
System.out.println(jsonBook);


String input = "{"author":"Max Tegmark","releaseYear":2017,"book_title":"Life 3.0"}";
Book bookReconstructed = mapper.readValue(input, Book.class);
System.out.print(bookReconstructed);

结果是:

{"author":"Max Tegmark","releaseYear":2014,"bt":"Our Mathematical Universe"}
Book{title='Life 3.0', author='Max Tegmark', releaseYear=2017}

结论

在这个简短的教程中,我们了解了 Jackson 如何将对象字段映射到 JSON,以及如何在序列化之前更改字段的名称。 我们还探索了使用不同的 JSON 名称进行序列化和反序列化的想法,使用 @JsonProperty 方法级别的注释,而不是字段级别的注释。

时间戳记:

更多来自 堆栈滥用