掌握JSON数据与编程语言对象之间的转换方法
JSON解析与序列化是处理JSON数据的两个核心过程,它们实现了JSON字符串与编程语言对象之间的相互转换。
编程语言中的数据结构
对象 → JSON字符串
数据交换格式
JSON字符串 → 对象
编程语言中的数据结构
将JSON字符串转换为编程语言对象的过程。
JSON.parse()将编程语言对象转换为JSON字符串的过程。
JSON.stringify()JSON.parse() 方法将JSON字符串解析为JavaScript对象。
// JSON字符串
const jsonString = '{"name": "张三", "age": 30, "isStudent": false}';
// 解析为JavaScript对象
const obj = JSON.parse(jsonString);
console.log(obj.name); // "张三"
console.log(obj.age); // 30
console.log(obj.isStudent); // false
reviver函数可以在解析过程中对结果进行转换。
const jsonString = '{"name": "张三", "age": 30, "birthDate": "1990-05-15"}';
const obj = JSON.parse(jsonString, function(key, value) {
// 将日期字符串转换为Date对象
if (key === 'birthDate') {
return new Date(value);
}
// 将年龄转换为字符串
if (key === 'age') {
return value + '岁';
}
return value;
});
console.log(obj.birthDate); // Date对象
console.log(obj.age); // "30岁"
解析无效的JSON字符串会抛出异常,需要使用try-catch处理。
function safeParse(jsonString) {
try {
return JSON.parse(jsonString);
} catch (error) {
console.error('JSON解析错误:', error.message);
return null;
}
}
// 有效的JSON
const validResult = safeParse('{"name": "张三"}');
console.log(validResult); // {name: "张三"}
// 无效的JSON
const invalidResult = safeParse('{name: "张三"}'); // 缺少引号
console.log(invalidResult); // null
JSON.stringify() 方法将JavaScript值转换为JSON字符串。
// JavaScript对象
const obj = {
name: "张三",
age: 30,
isStudent: false,
hobbies: ["阅读", "游泳"]
};
// 序列化为JSON字符串
const jsonString = JSON.stringify(obj);
console.log(jsonString);
// '{"name":"张三","age":30,"isStudent":false,"hobbies":["阅读","游泳"]}'
replacer可以是一个函数或数组,用于控制序列化过程中哪些属性被包含在结果中。
const obj = {
name: "张三",
age: 30,
password: "secret123",
isAdmin: true
};
// 使用replacer函数过滤属性
const jsonString = JSON.stringify(obj, function(key, value) {
// 排除密码字段
if (key === 'password') {
return undefined;
}
return value;
});
console.log(jsonString);
// '{"name":"张三","age":30,"isAdmin":true}'
const obj = {
name: "张三",
age: 30,
email: "zhangsan@example.com",
phone: "13800138000"
};
// 只序列化指定的属性
const jsonString = JSON.stringify(obj, ['name', 'age']);
console.log(jsonString);
// '{"name":"张三","age":30}'
space参数用于控制输出字符串的缩进,提高可读性。
const obj = {
name: "张三",
age: 30,
address: {
city: "北京",
country: "中国"
}
};
// 不缩进
console.log(JSON.stringify(obj));
// '{"name":"张三","age":30,"address":{"city":"北京","country":"中国"}}'
// 缩进2个空格
console.log(JSON.stringify(obj, null, 2));
// {
// "name": "张三",
// "age": 30,
// "address": {
// "city": "北京",
// "country": "中国"
// }
// }
// 使用制表符缩进
console.log(JSON.stringify(obj, null, '\t'));
// {
// "name": "张三",
// "age": 30,
// "address": {
// "city": "北京",
// "country": "中国"
// }
// }
JSON.stringify()在序列化时会遵循特定规则:
对象可以定义toJSON方法来自定义序列化行为。
class User {
constructor(name, age, email) {
this.name = name;
this.age = age;
this.email = email;
this.createdAt = new Date();
}
// 自定义序列化
toJSON() {
return {
name: this.name,
age: this.age,
email: this.email,
createdAt: this.createdAt.toISOString().split('T')[0] // 只保留日期部分
};
}
}
const user = new User("李四", 25, "lisi@example.com");
const jsonString = JSON.stringify(user);
console.log(jsonString);
// '{"name":"李四","age":25,"email":"lisi@example.com","createdAt":"2023-10-05"}'
当对象存在循环引用时,JSON.stringify会抛出错误。可以使用自定义replacer函数处理。
// 创建循环引用
const obj = { name: "循环引用示例" };
obj.self = obj; // 循环引用
// 自定义replacer处理循环引用
function circularReplacer() {
const seen = new WeakSet();
return function(key, value) {
if (typeof value === 'object' && value !== null) {
if (seen.has(value)) {
return '[Circular]';
}
seen.add(value);
}
return value;
};
}
const jsonString = JSON.stringify(obj, circularReplacer());
console.log(jsonString);
// '{"name":"循环引用示例","self":"[Circular]"}'
对于大型对象的序列化,可以考虑以下优化策略:
const largeObject = {
// ... 大量数据
id: 123,
name: "大型对象",
metadata: { /* 大量元数据 */ },
content: { /* 大量内容数据 */ }
};
// 只序列化需要的字段
function serializeSummary(obj) {
return JSON.stringify({
id: obj.id,
name: obj.name
// 不包含metadata和content
});
}
const summary = serializeSummary(largeObject);
console.log(summary); // '{"id":123,"name":"大型对象"}'
import json
# JSON解析
json_string = '{"name": "张三", "age": 30}'
python_dict = json.loads(json_string)
print(python_dict["name"]) # 张三
# JSON序列化
python_obj = {"name": "李四", "age": 25}
json_string = json.dumps(python_obj, ensure_ascii=False)
print(json_string) # {"name": "李四", "age": 25}
# 美化输出
pretty_json = json.dumps(python_obj, indent=2, ensure_ascii=False)
print(pretty_json)
import com.fasterxml.jackson.databind.ObjectMapper;
// JSON解析
String jsonString = "{\"name\":\"张三\",\"age\":30}";
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> map = mapper.readValue(jsonString, Map.class);
System.out.println(map.get("name")); // 张三
// JSON序列化
Map<String, Object> obj = new HashMap<>();
obj.put("name", "李四");
obj.put("age", 25);
String json = mapper.writeValueAsString(obj);
System.out.println(json); // {"name":"李四","age":25}
// 美化输出
String prettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
System.out.println(prettyJson);
using System.Text.Json;
// JSON解析
string jsonString = "{\"name\":\"张三\",\"age\":30}";
var obj = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonString);
Console.WriteLine(obj["name"]); // 张三
// JSON序列化
var data = new { name = "李四", age = 25 };
string json = JsonSerializer.Serialize(data);
Console.WriteLine(json); // {"name":"李四","age":25}
// 美化输出
var options = new JsonSerializerOptions { WriteIndented = true };
string prettyJson = JsonSerializer.Serialize(data, options);
Console.WriteLine(prettyJson);
| 语言 | 解析方法 | 序列化方法 | 主要库 |
|---|---|---|---|
| JavaScript | JSON.parse() | JSON.stringify() | 内置 |
| Python | json.loads() | json.dumps() | json (标准库) |
| Java | ObjectMapper.readValue() | ObjectMapper.writeValueAsString() | Jackson, Gson |
| C# | JsonSerializer.Deserialize() | JsonSerializer.Serialize() | System.Text.Json |
| PHP | json_decode() | json_encode() | 内置 |
| Ruby | JSON.parse() | JSON.generate() | json (标准库) |