杰瑞科技汇

如何将JSONObject转为Java对象?

下面我将为你详细讲解几种主流的实现方式,从最简单到最灵活,并提供完整的代码示例。

如何将JSONObject转为Java对象?-图1
(图片来源网络,侵删)

核心概念

无论使用哪种库,基本原理都是一样的:

  1. 定义 Java 类(POJO/DTO):创建一个 Java 类,其字段和结构与 JSON 对象的键值对相对应。
  2. 使用 JSON 库:调用库提供的解析方法,将 JSON 字符串作为输入,Java 类作为目标类型。
  3. 库自动映射:JSON 库会自动读取 JSON 数据,并将其填充到 Java 对象的字段中。

使用 Jackson (推荐)

Jackson 是目前 Java 生态中最流行、功能最强大的 JSON 处理库之一,Spring Boot 默认就集成了它。

添加依赖 (Maven)

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

准备 JSON 和 Java 类

假设我们有以下 JSON 字符串:

{
  "name": "张三",
  "age": 30,
  "isStudent": false,
  "address": {
    "city": "北京",
    "street": "中关村大街1号"
  },
  "phoneNumbers": [
    "13800138000",
    "13900139000"
  ]
}

我们需要创建对应的 Java 类,注意嵌套对象和数组。

如何将JSONObject转为Java对象?-图2
(图片来源网络,侵删)
// Address.java
public class Address {
    private String city;
    private String street;
    // 必须有无参构造器
    public Address() {}
    // Getter 和 Setter 方法
    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; }
    // (可选) toString() 方法方便打印
    @Override
    public String toString() {
        return "Address{" + "city='" + city + '\'' + ", street='" + street + '\'' + '}';
    }
}
// Person.java
import java.util.List;
public class Person {
    private String name;
    private int age;
    private boolean isStudent;
    private Address address;
    private List<String> phoneNumbers;
    // 必须有无参构造器
    public Person() {}
    // 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 Address getAddress() { return address; }
    public void setAddress(Address address) { this.address = address; }
    public List<String> getPhoneNumbers() { return phoneNumbers; }
    public void setPhoneNumbers(List<String> phoneNumbers) { this.phoneNumbers = phoneNumbers; }
    // (可选) toString() 方法方便打印
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", isStudent=" + isStudent +
                ", address=" + address +
                ", phoneNumbers=" + phoneNumbers +
                '}';
    }
}

进行转换

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonExample {
    public static void main(String[] args) {
        // 1. 创建 ObjectMapper 实例
        ObjectMapper objectMapper = new ObjectMapper();
        // 2. JSON 字符串
        String jsonString = "{\n" +
                "  \"name\": \"张三\",\n" +
                "  \"age\": 30,\n" +
                "  \"isStudent\": false,\n" +
                "  \"address\": {\n" +
                "    \"city\": \"北京\",\n" +
                "    \"street\": \"中关村大街1号\"\n" +
                "  },\n" +
                "  \"phoneNumbers\": [\n" +
                "    \"13800138000\",\n" +
                "    \"13900139000\"\n" +
                "  ]\n" +
                "}";
        try {
            // 3. 调用 readValue 方法进行转换
            // 参数1: JSON字符串
            // 参数2: 要转换成的Java类对象
            Person person = objectMapper.readValue(jsonString, Person.class);
            // 4. 验证结果
            System.out.println("转换成功!");
            System.out.println(person);
            System.out.println("姓名: " + person.getName());
            System.out.println("城市: " + person.getAddress().getCity());
        } catch (JsonProcessingException e) {
            System.err.println("JSON 解析失败!");
            e.printStackTrace();
        }
    }
}

输出结果:

转换成功!
Person{name='张三', age=30, isStudent=false, address=Address{city='北京', street='中关村大街1号'}, phoneNumbers=[13800138000, 13900139000]}
姓名: 张三
城市: 北京

使用 Gson

Google 的 Gson 是另一个非常流行且易用的 JSON 库。

添加依赖 (Maven)

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

进行转换

Java 类 (Person.java, Address.java) 的定义与 Jackson 方案完全相同。

import com.google.gson.Gson;
public class GsonExample {
    public static void main(String[] args) {
        // 1. 创建 Gson 实例
        Gson gson = new Gson();
        // 2. JSON 字符串 (与上面相同)
        String jsonString = "{\n" +
                "  \"name\": \"张三\",\n" +
                "  \"age\": 30,\n" +
                "  \"isStudent\": false,\n" +
                "  \"address\": {\n" +
                "    \"city\": \"北京\",\n" +
                "    \"street\": \"中关村大街1号\"\n" +
                "  },\n" +
                "  \"phoneNumbers\": [\n" +
                "    \"13800138000\",\n" +
                "    \"13900139000\"\n" +
                "  ]\n" +
                "}";
        // 3. 调用 fromJson 方法进行转换
        // 参数1: JSON字符串
        // 参数2: 要转换成的Java类对象
        Person person = gson.fromJson(jsonString, Person.class);
        // 4. 验证结果
        System.out.println("转换成功!");
        System.out.println(person);
    }
}

输出结果与 Jackson 方案完全一致。

如何将JSONObject转为Java对象?-图3
(图片来源网络,侵删)

使用 JSON-P / JSON-P (Java EE 标准)

如果你的项目是基于 Java EE 或 Jakarta EE 的,可以使用内置的 API。

无需额外依赖

进行转换

这种方式更偏向于手动解析,不如 Jackson/Gson 自动化。

import javax.json.JsonObject;
import javax.json.JsonReader;
import java.io.StringReader;
public class JsonpExample {
    public static void main(String[] args) {
        String jsonString = "{\"name\":\"张三\", \"age\":30}";
        try (JsonReader reader = Json.createReader(new StringReader(jsonString))) {
            // 1. 解析成 JsonObject
            JsonObject jsonObject = reader.readObject();
            // 2. 手动创建 Java 对象并赋值
            Person person = new Person();
            person.setName(jsonObject.getString("name"));
            person.setAge(jsonObject.getInt("age"));
            System.out.println("转换成功!");
            System.out.println(person);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意:对于复杂的嵌套对象,这种方式会非常繁琐,它更适用于处理简单的 JSON 结构。


关键注意事项和最佳实践

  1. 无参构造器:Jackson 和 Gson 在创建对象实例时,会通过反射调用无参构造器,你的 Java 类必须提供一个无参构造器(即使不显式写出,Java 也会提供一个默认的)。

  2. Getter 和 Setter:库通过反射来访问和设置字段值,为每个私有字段提供公共的 gettersetter 方法是标准做法。

  3. 字段命名:默认情况下,JSON 的键(key)需要与 Java 类的字段名完全匹配(大小写敏感)。

    • 解决不匹配问题:可以使用注解来指定映射关系。
      • Jackson: @JsonProperty("json_key")
      • Gson: @SerializedName("json_key")

    示例 (使用 Jackson):

    public class Person {
        @JsonProperty("user_name") // 将 JSON 中的 "user_name" 映射到 name 字段
        private String name;
        // ... 其他字段
    }
  4. 处理未知字段:JSON 中有你的 Java 类没有定义的字段,默认情况下会抛出异常或被忽略。

    • Jackson: 可以在 ObjectMapper 上配置:
      objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    • Gson: 默认情况下会忽略未知字段。
  5. 日期处理:日期类型的转换需要特别注意,库通常需要指定日期格式。

    • Jackson: 使用 @JsonFormat 注解。
      @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
      private Date birthDate;

总结与选择

特性 Jackson Gson JSON-P/JSON-P
易用性 非常简单,API直观 非常简单,API更简洁 较繁琐,需要手动操作
功能 非常强大,支持流式API、树模型、复杂注解等 功能强大,但略逊于Jackson 功能基础,适合简单场景
性能 性能优异,是业界标杆 性能也很好 性能一般
集成 Spring Boot 默认集成,生态最好 独立性好,广泛使用 Java EE 内置
推荐场景 首选,尤其适用于 Spring 项目,任何复杂场景 优秀选择,适合任何项目,特别是需要轻量级解决方案时 简单任务、无外部依赖要求的 Java EE 项目

对于绝大多数 Java 开发者,Jackson 是最推荐的选择,因为它功能全面、性能卓越,并且与现代框架(如 Spring Boot)无缝集成,Gson 也是一个非常可靠的备选方案。

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