【JS-8-Json】深入理解JSON语法及Java中的JSON操作
1. JSON简介
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于ECMAScript的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
1.1 JSON的主要特点
- 易于人阅读和编写
- 易于机器解析和生成
- 支持多种数据结构:对象、数组、字符串、数字、布尔值和null
- 网络传输效率高(相比XML更简洁)
2. JSON语法格式详解
2.1 JSON基本结构
JSON由两种基本结构组成:
- 键值对集合:在各种语言中被实现为对象、记录、字典等
- 值的有序列表:在大多数语言中被实现为数组、列表等
2.2 JSON值类型
JSON支持以下数据类型:
类型 | 示例 |
---|---|
对象 | {"name":"John"} |
数组 | [1, 2, 3] |
字符串 | "hello" |
数字 | 123 或 12.3 |
布尔值 | true 或 false |
null | null |
2.3 JSON对象
JSON对象是一个无序的键值对集合,用花括号{}
包围:
{"name": "John","age": 30,"isStudent": false,"address": {"street": "123 Main St","city": "New York"},"hobbies": ["reading", "swimming"]
}
语法规则:
- 键必须是字符串,用双引号括起来
- 值可以是任意JSON数据类型
- 键值对之间用逗号分隔
- 最后一个键值对后不能有逗号
2.4 JSON数组
JSON数组是值的有序集合,用方括号[]
包围:
["apple","banana","orange",{"fruit": "grape","color": "purple"},[1, 2, 3]
]
语法规则:
- 数组元素可以是任意JSON数据类型
- 元素之间用逗号分隔
- 最后一个元素后不能有逗号
2.5 JSON字符串
JSON字符串必须用双引号括起来,支持以下转义字符:
转义序列 | 含义 |
---|---|
\" | 双引号 |
\\ | 反斜杠 |
\/ | 正斜杠 |
\b | 退格 |
\f | 换页 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\uXXXX | Unicode字符 |
示例:
{"message": "Hello,\nWorld!","unicode": "\u03A9" // 希腊字母Ω
}
3. Java中的JSON操作
Java中有多个流行的库可用于处理JSON,包括:
- org.json (官方JSON库)
- Gson (Google)
- Jackson
- Fastjson (阿里)
下面我们以Gson和Jackson为例进行介绍。
3.1 使用Gson处理JSON
3.1.1 添加依赖
Maven:
<dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.9</version>
</dependency>
Gradle:
implementation 'com.google.code.gson:gson:2.8.9'
3.1.2 基本操作
Java对象转JSON(序列化):
import com.google.gson.Gson;class Person {private String name;private int age;private boolean isStudent;// 构造方法、getter和setter省略
}public class Main {public static void main(String[] args) {Person person = new Person("John", 30, false);Gson gson = new Gson();String json = gson.toJson(person);System.out.println(json);// 输出: {"name":"John","age":30,"isStudent":false}}
}
JSON转Java对象(反序列化):
String json = "{\"name\":\"John\",\"age\":30,\"isStudent\":false}";
Person person = gson.fromJson(json, Person.class);
System.out.println(person.getName()); // 输出: John
处理复杂对象:
import java.util.List;class Address {private String street;private String city;// getter和setter省略
}class ComplexPerson {private String name;private Address address;private List<String> hobbies;// getter和setter省略
}// 使用示例
ComplexPerson person = new ComplexPerson();
person.setName("Alice");
person.setAddress(new Address("123 Main St", "New York"));
person.setHobbies(List.of("Reading", "Swimming"));Gson gson = new Gson();
String json = gson.toJson(person);
System.out.println(json);
// 输出: {"name":"Alice","address":{"street":"123 Main St","city":"New York"},"hobbies":["Reading","Swimming"]}
3.2 使用Jackson处理JSON
3.2.1 添加依赖
Maven:
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.13.0</version>
</dependency>
Gradle:
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.0'
3.2.2 基本操作
Java对象转JSON:
import com.fasterxml.jackson.databind.ObjectMapper;public class Main {public static void main(String[] args) throws Exception {Person person = new Person("John", 30, false);ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(person);System.out.println(json);// 输出: {"name":"John","age":30,"isStudent":false}}
}
JSON转Java对象:
String json = "{\"name\":\"John\",\"age\":30,\"isStudent\":false}";
Person person = mapper.readValue(json, Person.class);
System.out.println(person.getName()); // 输出: John
处理日期格式:
import java.util.Date;class Event {private String name;private Date date;// getter和setter省略
}ObjectMapper mapper = new ObjectMapper();
// 设置日期格式
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));Event event = new Event("Meeting", new Date());
String json = mapper.writeValueAsString(event);
System.out.println(json);
// 输出: {"name":"Meeting","date":"2023-05-20 14:30:00"}
3.3 JSON与集合操作
List转JSON:
List<Person> people = List.of(new Person("John", 30, false),new Person("Alice", 25, true)
);Gson gson = new Gson();
String json = gson.toJson(people);
System.out.println(json);
// 输出: [{"name":"John","age":30,"isStudent":false},{"name":"Alice","age":25,"isStudent":true}]
JSON转List:
String json = "[{\"name\":\"John\",\"age\":30,\"isStudent\":false},{\"name\":\"Alice\",\"age\":25,\"isStudent\":true}]";// 使用Gson
Type personListType = new TypeToken<List<Person>>(){}.getType();
List<Person> people = gson.fromJson(json, personListType);// 使用Jackson
List<Person> people = mapper.readValue(json, new TypeReference<List<Person>>(){});
3.4 处理JSON中的特殊结构
处理JSON数组:
String jsonArray = "[1, 2, 3, 4, 5]";// 使用Gson
int[] numbers = gson.fromJson(jsonArray, int[].class);// 使用Jackson
int[] numbers = mapper.readValue(jsonArray, int[].class);
处理嵌套JSON:
String complexJson = """
{"name": "Company Inc","employees": [{"name": "John", "age": 30},{"name": "Alice", "age": 25}],"departments": {"sales": {"head": "Mike", "size": 10},"it": {"head": "Sarah", "size": 15}}
}
""";// 使用Jackson
JsonNode rootNode = mapper.readTree(complexJson);
String companyName = rootNode.get("name").asText();
JsonNode employees = rootNode.get("employees");
String firstEmployeeName = employees.get(0).get("name").asText();
int itDepartmentSize = rootNode.path("departments").path("it").path("size").asInt();
4. JSON处理最佳实践
- 始终处理异常:JSON解析可能会抛出异常,应该妥善处理
- 使用合适的日期格式:明确指定日期格式以避免歧义
- 考虑性能:对于大型JSON,考虑使用流式API(如Jackson的JsonParser)
- 验证JSON:在反序列化前验证JSON格式
- 处理特殊字符:注意转义字符串中的特殊字符
- 使用注解控制序列化:如@JsonIgnore、@JsonProperty等
5. 性能比较
以下是几种常见JSON库的性能比较(仅供参考):
库 | 序列化速度 | 反序列化速度 | 内存占用 | 功能丰富度 |
---|---|---|---|---|
Jackson | 快 | 快 | 低 | 高 |
Gson | 中等 | 中等 | 中等 | 中等 |
Fastjson | 快 | 快 | 低 | 高 |
org.json | 慢 | 慢 | 高 | 低 |
选择建议:
- 需要最高性能:Jackson或Fastjson
- 需要简单易用:Gson
- 最小依赖:org.json
6. 总结
JSON作为一种轻量级的数据交换格式,在现代编程中扮演着重要角色。Java生态系统提供了多种强大的JSON处理库,开发者可以根据项目需求选择合适的工具。掌握JSON的语法规则和Java中的操作方法,能够大大提高开发效率和数据交互的可靠性。
无论是简单的数据转换还是复杂的嵌套结构处理,现代JSON库都能提供简洁高效的解决方案。在实际开发中,建议结合项目需求、性能要求和团队熟悉度来选择合适的JSON处理库。