杰瑞科技汇

Java JSON如何高效转Java对象?

核心概念:反序列化

将 JSON 字符串转换成 Java 对象的过程,在技术上称为 反序列化,这需要一个“映射”关系,即 JSON 中的键如何与 Java 对象中的属性(字段)对应起来。

Java JSON如何高效转Java对象?-图1
(图片来源网络,侵删)

使用 Jackson (最推荐)

Jackson 是目前 Java 生态中最流行、功能最强大的 JSON 处理库,Spring Framework 等许多主流框架都内置了它。

添加依赖

如果你使用 Maven,在 pom.xml 中添加依赖:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.2</version> <!-- 请使用最新版本 -->
</dependency>

如果你使用 Gradle,在 build.gradle 中添加:

implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.2' // 请使用最新版本

创建 Java 类(POJO)

你需要一个与 JSON 结构对应的 Java 类,JSON 的键名需要与 Java 类的属性名一致(或者通过注解进行映射)。

Java JSON如何高效转Java对象?-图2
(图片来源网络,侵删)

示例 JSON:

{
  "name": "张三",
  "age": 30,
  "isStudent": false,
  "courses": [
    "Java",
    "Spring Boot"
  ],
  "address": {
    "city": "北京",
    "street": "中关村大街1号"
  }
}

对应的 Java 类: User.java

import java.util.List;
import java.util.Map;
// 可以使用 @JsonIgnoreProperties(ignoreUnknown = true) 来忽略 JSON 中存在但 Java 类中没有的属性
// @JsonIgnoreProperties(ignoreUnknown = true) 
public class User {
    private String name;
    private int age;
    private boolean isStudent;
    private List<String> courses;
    private Address address; // 内部嵌套对象
    // 必须提供一个无参构造函数,Jackson 在反序列化时会使用它
    public User() {
    }
    // 建议提供 getter 和 setter 方法
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public boolean isStudent() {
        return isStudent;
    }
    public void setStudent(boolean student) {
        isStudent = student;
    }
    public List<String> getCourses() {
        return courses;
    }
    public void setCourses(List<String> courses) {
        this.courses = courses;
    }
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    // 为了方便打印结果,重写 toString() 方法
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", isStudent=" + isStudent +
                ", courses=" + courses +
                ", address=" + address +
                '}';
    }
}

Address.java

public class Address {
    private String city;
    private String street;
    public Address() {
    }
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public String getStreet() {
        return street;
    }
    public void setStreet(String street) {
        this.street = street;
    }
    @Override
    public String toString() {
        return "Address{" +
                "city='" + city + '\'' +
                ", street='" + street + '\'' +
                '}';
    }
}

执行转换

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonJsonToJavaExample {
    public static void main(String[] args) {
        // 1. 创建 ObjectMapper 实例(它是线程安全的,可以全局共用一个)
        ObjectMapper objectMapper = new ObjectMapper();
        // 2. 定义 JSON 字符串
        String jsonString = "{\"name\":\"张三\",\"age\":30,\"isStudent\":false,\"courses\":[\"Java\",\"Spring Boot\"],\"address\":{\"city\":\"北京\",\"street\":\"中关村大街1号\"}}";
        try {
            // 3. 调用 readValue 方法进行转换
            // 第一个参数是 JSON 字符串
            // 第二个参数是目标 Java 对象的 .class 文件
            User user = objectMapper.readValue(jsonString, User.class);
            // 4. 验证结果
            System.out.println("转换成功!");
            System.out.println(user);
            System.out.println("用户姓名: " + user.getName());
            System.out.println("用户所在城市: " + user.getAddress().getCity());
        } catch (JsonProcessingException e) {
            System.err.println("JSON 解析失败!");
            e.printStackTrace();
        }
    }
}

输出:

Java JSON如何高效转Java对象?-图3
(图片来源网络,侵删)
转换成功!
User{name='张三', age=30, isStudent=false, courses=[Java, Spring Boot], address=Address{city='北京', street='中关村大街1号'}}
用户姓名: 张三
用户所在城市: 北京

使用 Gson

Google 的 Gson 是另一个非常流行的 JSON 库,使用起来同样非常简单。

添加依赖

Maven (pom.xml):

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version> <!-- 请使用最新版本 -->
</dependency>

Gradle (build.gradle):

implementation 'com.google.code.gson:gson:2.10.1' // 请使用最新版本

创建 Java 类

Java 类的创建与 Jackson 方式完全相同,这里不再重复,你需要 User.javaAddress.java

执行转换

import com.google.gson.Gson;
public class GsonJsonToJavaExample {
    public static void main(String[] args) {
        // 1. 创建 Gson 实例(它也是线程安全的,可以全局共用)
        Gson gson = new Gson();
        // 2. 定义 JSON 字符串
        String jsonString = "{\"name\":\"张三\",\"age\":30,\"isStudent\":false,\"courses\":[\"Java\",\"Spring Boot\"],\"address\":{\"city\":\"北京\",\"street\":\"中关村大街1号\"}}";
        try {
            // 3. 调用 fromJson 方法进行转换
            // 第一个参数是 JSON 字符串或 Reader
            // 第二个参数是目标 Java 对象的 .class 文件
            User user = gson.fromJson(jsonString, User.class);
            // 4. 验证结果
            System.out.println("转换成功!");
            System.out.println(user);
            System.out.println("用户姓名: " + user.getName());
            System.out.println("用户所在城市: " + user.getAddress().getCity());
        } catch (Exception e) {
            System.err.println("JSON 解析失败!");
            e.printStackTrace();
        }
    }
}

输出结果与 Jackson 示例完全相同。


高级用法与常见问题

JSON 键名与 Java 属性名不一致

当 JSON 中的键名(user_name)与 Java 类中的属性名(userName)不一致时,需要使用注解来建立映射关系。

示例 JSON:

{
  "user_name": "李四",
  "user_age": 25
}

Java 类 (使用 Jackson):

public class UserWithDifferentKey {
    // @JsonProperty 注解用于将 JSON 中的 "user_name" 映射到 Java 属性 "userName"
    @JsonProperty("user_name")
    private String userName;
    @JsonProperty("user_age")
    private int userAge;
    // ... getter, setter, toString ...
}

Java 类 (使用 Gson): Gson 提供了类似的注解 @SerializedName

import com.google.gson.annotations.SerializedName;
public class UserWithDifferentKey {
    // @SerializedName 注解用于将 JSON 中的 "user_name" 映射到 Java 属性 "userName"
    @SerializedName("user_name")
    private String userName;
    @SerializedName("user_age")
    private int userAge;
    // ... getter, setter, toString ...
}

处理 JSON 中的日期

JSON 本身没有标准的日期类型,通常用字符串表示,Jackson 和 Gson 都提供了强大的日期处理功能。

示例 JSON:

{
  "name": "王五",
  "birthDate": "1990-01-01"
}

Java 类 (使用 Jackson):

import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
public class UserWithDate {
    private String name;
    // @JsonFormat 注解可以指定日期的格式
    // pattern: 日期格式
    // timezone: 时区
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private Date birthDate;
    // ... getter, setter, toString ...
}

Java 类 (使用 Gson): Gson 在创建 Gson 实例时可以配置日期格式。

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.Date;
// ...
Gson gson = new GsonBuilder()
        .setDateFormat("yyyy-MM-dd") // 设置全局日期格式
        .create();

将 JSON 转换为 MapList

如果你不想创建对应的 Java 类,或者 JSON 结构非常动态,可以直接将其转换为 Map<String, Object>List<Object>

示例 (使用 Jackson):

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;
public class JsonToMapExample {
    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = "{\"name\":\"赵六\",\"age\":40,\"city\":\"上海\"}";
        // 使用 TypeReference 来明确指定泛型类型,这是关键!
        Map<String, Object> dataMap = objectMapper.readValue(jsonString, new TypeReference<Map<String, Object>>() {});
        System.out.println(dataMap);
        System.out.println("姓名: " + dataMap.get("name"));
        System.out.println("年龄: " + dataMap.get("age")); // 值是 Integer 类型
    }
}

总结与推荐

特性 Jackson Gson
流行度 非常高,是事实上的标准,Spring 默认使用。 非常高,Google 出品,稳定可靠。
性能 通常被认为性能更优,功能更强大。 性能也很好,但在某些极端场景下略逊于 Jackson。
API 设计 功能全面,但 API 相对复杂一些。 API 设计非常简洁、直观,易于上手。
数据绑定 支持强大的数据绑定、流式 API、树模型等。 主要专注于数据绑定,API 简单。
集成 与 Spring 等框架无缝集成。 需要手动配置,但集成也很容易。

如何选择?

  • 新项目,特别是基于 Spring 的项目强烈推荐 Jackson,因为它已经是生态的一部分,无需额外引入,并且功能最全面。
  • 独立的小项目或追求 API 简洁性Gson 是一个绝佳的选择,它的 API 非常干净,学习成本低。
  • 需要处理复杂 JSON 或追求极致性能Jackson 更有优势。

对于绝大多数 Java 熟练掌握 Jackson 是非常有必要的

分享:
扫描分享到社交APP
上一篇
下一篇