1# ylong_json 用户指南
2
3`ylong_json` 模块提供了 JSON 语法格式文本或字符串的序列化功能,以及对应生成实例的反序列化功能。此外,`ylong_json`模块还适配了第三方库 `serde`。对于实现了 `serde` 库中特定 trait 的结构,可以对其进行序列化与反序列化操作。
4
5如果需要查看详细的接口说明请查看对应接口的 docs,可以使用 `cargo doc --open` 生成并查看 docs。
6
7## 功能一:生成 JSON 实例
8
9(1)可以使用 `JsonValue` 所具有的四种方法从不同的来源生成 `JsonValue` 实例:
10```rust
11use std::fs::File;
12use std::str::FromStr;
13use std::io::Read;
14use ylong_json::JsonValue;
15
16fn create_json_value_instance() {
17    let str: &str = "";
18    // 可以使用 from_str 接口,从 &str 类型尝试生成 JsonValue 实例。
19    // 如果传入的 &str 不符合 JSON 语法,会返回对应的 Error。
20    let json_value = JsonValue::from_str(str);
21
22    let text: String = String::from("");
23    // 可以使用 from_text 接口,从一系列实现 AsRef<[u8]> 的类型生成 JsonValue 实例。
24    // 如果传入的文本内容不符合 JSON 语法,会返回对应的 Error。
25    let json_value = JsonValue::from_text(text);
26
27    let path: &str = "";
28    // 可以使用 from_file 接口,从对应路径的文件读取内容,并尝试生成 JsonValue 实例。
29    // 如果传入的 path 不合法或者文本内容不符合 JSON 语法,会返回对应的 Error。
30    let json_value = JsonValue::from_file(path);
31
32    let mut reader: Box<dyn Read> = Box::new(File::open("").unwrap());
33    // 可以使用 from_reader 接口,从实现了 io::Read 的实例中读取文本,并尝试生成 JsonValue 实例。
34    // 如果读取失败或者从 reader 中读取的内容不符合 JSON 语法,会返回对应的 Error。
35    let json_value = JsonValue::from_reader(&mut reader);
36}
37```
38当 `JsonValue` 实例创建成功后,就可以尝试读取和修改对应的内容了。
39
40(2)如果 JSON 文本中的类型实现了第三方库 `serde::Deserialize` trait,则可以直接将文本内容反序列化为该类型的实例。
41```rust
42use std::fs::File;
43use serde::Deserialize;
44use ylong_json::deserializer::{from_reader, from_slice, from_st};
45fn deserialize_json_to_instance() {
46    #[derive(Deserialize, PartialEq, Debug)]
47    struct Example {
48        int: u32,
49        seq: Vec<String>,
50        tup: (i32, i32, i32),
51    }
52
53    // 可以使用 from_str 接口,从 &str 类型生成实例。
54    // 如果传入的 &str 不符合 JSON 语法,会返回对应的 Error。
55    let tr = r#"{"int":1,"seq":["abcd","efgh"],"tup":[1,2,3]}"#;
56    let example = from_str::<Example>(str).unwrap();
57
58    // 可以使用 from_slice 接口,从 &u8 类型生成实例。
59    // 如果传入的 &u8 不符合 JSON 语法,会返回对应的 Error。
60    let slice = str.as_bytes();
61    let example = from_slice::<Example>(slice).unwrap();
62
63
64    // 可以使用 from_reader 接口,从实现了 io::Write 的位置、文件、io流等生成实例。
65    // 如果传入的文本内容不符合 JSON 语法,会返回对应的 Error。
66    let mut file: File = File::open("./example.txt").unwrap();
67    let example = from_reader::<Example>(file).unwrap();
68}
69```
70
71### 功能二:读取、修改键值对
72`JsonValue` 实例生成成功后,可以通过各种下标来查找对应的键值对(获取到对应 `JsonValue` 的普通引用)。
73
74&str 和 String 类型的下标可以用于查找 Object 内的键值对;usize 类型的下标可以用于查找 Array 内的键值对。
75```rust
76use std::str::FromStr;
77use ylong_json::JsonValue;
78
79// 示例的 JSON 字符串
80const JSON_TEXT: &str = r#"
81{
82    "key": "value",
83    "array": [1, 2, 3]
84}
85"#;
86
87fn find_key_value_pair() {
88    // 根据示例字符串创建 JsonValue 实例,语法正确所以此处解析必定成功,使用 unwrap。
89    let json_value = JsonValue::from_str(JSON_TEXT).unwrap();
90
91    // 由于 json 本身也是一个表,所以可以使用 &str 类型获取内部值的普通引用。
92    let value: &JsonValue = &json_value["key"];
93
94    // 可以通过 &str 类型先获取到 “array” 成员的普通引用,再根据 usize 类型获取对应元素的普通引用。
95    let array_item: &JsonValue = &json_value["array"][0];
96
97    // 如果尝试查找一个不存在表中的键,会返回 &JsonValue::Null。
98    let no_such_key: &JsonValue = &json_value["no_such_key"];
99
100    // 对 Array 类型查找时,若下标超过 Array 长度,也会返回 &JsonValue::Null。
101    let no_such_index: &JsonValue = &json_value["array"][100];
102
103    // 对一个 Object 和 Array 类型以外的 JsonValue 类型使用下标访问也会返回 &JsonValue::Null。
104    let invalid_index: &JsonValue = &json_value["key"]["invalid"];
105    let invalid_index: &JsonValue = &json_value["key"][0];
106}
107```
108也可以通过相同方法获取到对应 `JsonValue` 的可变引用,获取到可变引用后可以对其进行修改,修改时需要注意符合 JSON 语法。
109```rust
110use ylong_json::JsonValue;
111
112// 示例的 JSON 字符串
113const JSON_TEXT: &str = r#"
114{
115    "key": "value",
116    "array": [1, 2, 3]
117}
118"#;
119
120fn modify_key_value_pair() {
121    // 根据示例字符串创建 JsonValue 实例,语法正确所以此处解析必定成功,使用 unwrap。
122    // 此处由于需要获取可变引用,JSON 实例需要可变。
123    let mut json_value = JsonValue::from_str(JSON_TEXT).unwrap();
124
125    // 通过 “key” 获取到对应成员的可变引用,并将其设置为数值 123。
126    // 库中给许多基本类型实现了从自身到 JsonValue 的转换,所以可以通过 into() 方法转换为 JsonValue。
127    // 执行此句代码后,表中内容如下:
128    // {
129    //      "key": 123,
130    //      "array": [1, 2, 3]
131    // }
132    json_value["key"] = 123_i32.into();
133
134    // 通过 “array” 和下标 0 获取到对应成员的可变引用,并将其设置为数值 123。
135    // 执行此句代码后,表中内容如下:
136    // {
137    //      "key": 123,
138    //      "array": [123, 2, 3]
139    // }
140    json_value["array"][0] = 123_i32.into();
141
142    // 如果尝试获取一个不存在表中的键的可变引用,会在表中插入该键且对应值为 JsonValue::Null,并在此基础上进行修改。
143    // 执行此行代码后,json_value 中会增加一个成员 “no_such_key”,且值为数值 123。
144    // 表中内容如下:
145    // {
146    //      "key": 123,
147    //      "array": [123, 2, 3],
148    //      "no_such_key": 123
149    // }
150    json_value["no_such_key"] = 123_i32.into();
151
152    // 对 Array 类型的成员尝试获取可变引用时,若下标超过 Array 长度,
153    // 会在 Array 末尾插入一个 JsonValue::Null,并返回该位置的可变引用。
154    // 执行此行代码后,json_value 的 “array” 成员的长度变为 4。
155    // 表中内容如下:
156    // {
157    //      "key": 123,
158    //      "array": [123, 2, 3, 123],
159    //      "no_such_key": 123
160    // }
161    json_value["array"][100] = 123_i32.into();
162
163    // 对一个非 Object 类型使用 &str 类型或 String 下标获取可变引用时,
164    // 会将该值替换为一个空 Object,然后再用此下标对其进行访问。
165    // 执行此代码后,json_value 的 array 成员变成 Object 类型,且含有一个键值对:“key” => 123。
166    // 表中内容如下:
167    // {
168    //      "key": 123,
169    //      "array": {
170    //          "key": 123
171    //      },
172    //      "no_such_key": 123
173    // }
174    json_value["array"]["key"] = 123_i32.into();
175
176    // 对一个非 Array 类型使用 usize 类型下标获取可变引用时,
177    // 会将该值替换成一个空 Array,然后再用此下标对其进行访问。
178    // 执行此代码后,json_value 的 key 成员变成 Array 类型,且含有一个成员: key[0] => 123
179    // 表中内容如下:
180    // {
181    //      "key": [123],
182    //      "array": {
183    //          "key": 123
184    //      },
185    //      "no_such_key": 123
186    // }
187    json_value["key"][0] = 123_i32.into();
188}
189```
190
191### 功能三:输出 JSON 文本
192(1)当拥有一个 `JsonValue` 实例时,可以将该 `JsonValue` 实例转化成文本并输出到指定位置:字符串、文件、网络等。
193```rust
194use std::fs::File;
195use ylong_json::JsonValue;
196
197fn output_json_text(json_value: JsonValue) {
198    // 使用 to_compact_string() 接口将 json_value 输出成一个字符串。
199    let string = json_value.to_compact_string().unwrap();
200
201    // 使用 compact_encode() 接口将 JSON 文本输出到指定实现了 io::Write 的位置,文件、io流等。
202    let mut file: File = File::open("").unwrap();
203    let _ = json_value.compact_encode(&mut file);
204}
205```
206由于 JSON 内部元素没有较强的顺序要求,所以成员的输出顺序会有一定随机性,但是不影响 JSON 文本的语义。
207
208(2)可以将一个实现了第三方库 `serde::Serialize` trait 的类型实例序列化为 JSON 文本。
209```rust
210use std::fs::File;
211use serde::Serialize;
212use ylong_json::serializer_compact::{to_string, to_writer};
213
214fn output_json_text() {
215    #[derive(Serialize)]
216    struct Exmaple {
217        int: u32,
218        seq: Vec<&'static str>,
219        tup: (i32, i32, i32),
220    }
221
222    let example = Example {
223        int: 1,
224        seq: vec!["a", "b"],
225        tup: (1, 2, 3),
226    };
227
228    // 使用 to_string() 接口将 value 输出成一个字符串。
229    let string = to_string(&example).unwrap();
230
231    // 使用 to_writer() 接口将 JSON 文本输出到指定实现了 io::Write 的位置,文件、io流等。
232    let mut file: File = File::open("./example.txt").unwrap();
233    let _ = to_writer(&example, &mut file);
234}
235```