上一篇
用 Gson/Jackson 等库将 Java 对象序列化为 JSON 字符串,再写入文件
以下是关于 Java 如何创建 JSON 文件 的完整指南,涵盖核心概念、多种实现方式、代码示例及常见问题解答,本文旨在帮助开发者系统化掌握这一技能,适用于新手入门与进阶优化。
前置知识与工具准备
1 什么是 JSON?
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,以键值对形式存储数据,支持嵌套结构、数组和多种数据类型(字符串、数字、布尔值等),其优势在于跨平台兼容性强、可读性高,广泛用于前后端交互、配置文件等领域。
2 Java 生态中的 JSON 处理方案
| 工具/框架 | 特点 | 适用场景 |
|---|---|---|
org.json |
轻量级纯 Java 实现,API 简单直接 | 小型项目、快速原型开发 |
Gson |
Google 开发,基于注解映射复杂对象 | 业务逻辑与 DTO 转换 |
Jackson |
高性能、功能全面(支持流式解析、自定义序列化规则) | 企业级应用、大数据量 |
FastJson |
阿里巴巴开源,速度快,支持自动装箱/拆箱 | 国内项目、性能敏感场景 |
3 环境依赖配置
若需使用第三方库,需在项目中引入对应依赖:
- Maven 坐标示例:
<!-Gson --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.10.1</version> </dependency> <!-Jackson --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.2</version> </dependency>
- Gradle 同步更新:通过IDE自动下载或手动添加至
build.gradle。
核心实现方法详解
1 方法一:使用 org.json 库(无依赖)
适用场景:无需引入外部库的简单场景。
步骤:
- 创建 JSONObject/JSONArray:通过
new JSONObject()或new JSONArray()初始化容器。 - 填充数据:调用
put(key, value)方法添加键值对。 - 写入文件:利用
FileWriter将 JSON 字符串写入文件。
代码示例:
import org.json.JSONObject;
import java.io.FileWriter;
import java.io.IOException;
public class OrgJsonExample {
public static void main(String[] args) throws IOException {
// 1. 创建 JSON 对象
JSONObject jsonObj = new JSONObject();
jsonObj.put("name", "张三");
jsonObj.put("age", 25);
jsonObj.put("hobbies", new String[]{"阅读", "游泳"}); // 支持数组
jsonObj.put("address", new JSONObject().put("city", "北京").put("street", "长安街")); // 嵌套对象
// 2. 写入文件
try (FileWriter file = new FileWriter("user_info.json")) {
file.write(jsonObj.toString(4)); // 参数为缩进空格数,美化输出
}
}
}
输出文件内容:
{
"name": "张三",
"age": 25,
"hobbies": [
"阅读",
"游泳"
],
"address": {
"city": "北京",
"street": "长安街"
}
}
2 方法二:使用 Gson 库(推荐)
适用场景:需要将 Java 对象与 JSON 相互转换的场景。
步骤:
- 定义 POJO 类:创建与 JSON 结构匹配的 Java 类。
- 实例化对象并赋值:构造业务对象。
- 序列化为 JSON:通过
Gson的toJson()方法生成 JSON 字符串。 - 写入文件:同上。
代码示例:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
// 1. 定义 POJO 类
class User {
private String name;
private int age;
private List<String> hobbies;
private Address address; // 嵌套对象
// getters & setters 省略(Gson 可通过字段名反射)
}
class Address {
private String city;
private String street;
// getters & setters 省略
}
public class GsonExample {
public static void main(String[] args) throws IOException {
// 2. 构造对象
User user = new User();
user.setName("李四");
user.setAge(30);
user.setHobbies(List.of("摄影", "旅行"));
user.setAddress(new Address() {{ setCity("上海"); setStreet("南京路"); }});
// 3. 序列化为 JSON(启用格式化输出)
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String jsonStr = gson.toJson(user);
// 4. 写入文件
try (FileWriter file = new FileWriter("user_gson.json")) {
file.write(jsonStr);
}
}
}
优势:自动处理复杂类型(如日期、集合),支持注解定制字段映射(如 @SerializedName)。
3 方法三:使用 Jackson 库(工业级标准)
适用场景:高性能、高灵活性需求的企业级应用。
步骤:
- 定义 POJO 类:同 Gson。
- 创建 ObjectMapper:配置全局参数(如日期格式、空值处理)。
- 序列化与写入:直接调用
writeValue()方法写入文件。
代码示例:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.io.File;
import java.util.List;
public class JacksonExample {
public static void main(String[] args) throws Exception {
// 1. 构造对象(同 Gson 示例)
User user = new User();
user.setName("王五");
user.setAge(35);
user.setHobbies(List.of("编程", "音乐"));
user.setAddress(new Address() {{ setCity("广州"); setStreet("天河路"); }});
// 2. 配置 ObjectMapper
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT); // 启用缩进
mapper.findAndRegisterModules(); // 自动注册常用模块(如 Joda-Time)
// 3. 直接写入文件
mapper.writeValue(new File("user_jackson.json"), user);
}
}
高级特性:支持流式 API(JsonGenerator)、自定义序列化器(JsonSerializer)、反序列化校验等。
关键注意事项与最佳实践
1 数据类型匹配问题
| Java 类型 | JSON 类型 | 备注 |
|---|---|---|
String |
字符串 | |
Integer |
数值 | 避免浮点数精度丢失 |
Boolean |
true/false | |
Date/LocalDateTime |
字符串(默认 ISO 格式) | 需配置自定义日期格式 |
Map |
JSON 对象 | |
List/Set |
JSON 数组 |
解决方案:使用 @JsonFormat(Jackson)或 @Since(Gson)注解指定格式。
2 特殊字符转义
- 换行符:
n→\n - 引号: →
" - 反斜杠:
→\ - Unicode 字符:如 →
u00E9
示例:若需在 JSON 中包含双引号,应转义为 "。
3 性能优化建议
| 场景 | 优化策略 | 效果 |
|---|---|---|
| 高频小对象序列化 | 复用 ObjectMapper 实例 |
减少对象创建开销 |
| 大文件写入 | 使用 BufferedWriter 包装流 |
提升 I/O 效率 |
| 多线程环境 | 采用线程安全的 ObjectMapperPool |
避免并发竞争 |
| 动态字段处理 | 使用 JsonNode 替代预定义 POJO |
灵活应对未知字段 |
常见错误排查表
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| JSON 字符串含非规字符 | 未转义特殊字符(如 ) | 使用 replaceAll() 预处理 |
| 字段缺失或顺序错误 | POJO 字段名与 JSON 不匹配 | 使用 @JsonProperty 注解 |
| 循环引用导致栈溢出 | 对象间存在双向关联 | 禁用循环引用(disableCircularReferenceDetect) |
| 日期序列化为数字 | 未配置日期格式 | 添加 @JsonFormat(shape=Shape.STRING) |
相关问答 FAQs
Q1: 如何在 Java 中读取已生成的 JSON 文件?
A: 根据使用的库选择对应方法:
- org.json:
JSONObject obj = new JSONObject(new FileReader("file.json")); - Gson:
User user = gson.fromJson(new FileReader("file.json"), User.class); - Jackson:
User user = mapper.readValue(new File("file.json"), User.class);
Q2: 如何处理 JSON 中的 null 值?
A: 各库默认行为不同:
- org.json:
optString("key")可返回空字符串而非 null。 - Gson: 配置
serializeNulls()决定是否序列化 null。 - Jackson: 通过
@JsonInclude(JsonInclude.Include.NON_NULL)注解过滤 null。
