mirror of
https://gitee.com/openharmony/commonlibrary_rust_ylong_json
synced 2024-11-30 10:50:31 +00:00
!4 【ylong_json】更新 README & RELEASE_NOTE & user_guide
Merge pull request !4 from 王柄涵/master
This commit is contained in:
commit
2d8a7526d3
319
README.md
319
README.md
@ -1,273 +1,47 @@
|
||||
# ylong_json
|
||||
|
||||
## Introduction
|
||||
|
||||
The `ylong_json` module provides serialization of text or string in JSON syntax format and deserialization of corresponding generated instances.
|
||||
|
||||
`ylong_json` contains the following core functionality:
|
||||
### ylong_json in Openharmony
|
||||
![structure](./figure/ylong_json_oh_relate.png)
|
||||
Here is the description of the key fields in the figure above:
|
||||
- `ylong_json` : System component that provides json serialization and deserialization capabilities
|
||||
- `serde` : Third-party library for efficient and generic serialization and deserialization of Rust data structures.
|
||||
|
||||
### Function 1: Generates a JSON instance
|
||||
`ylong_json` provides the ability to generate an instance of `JsonValue` from JSON text or string. You need to use a series of instance creation methods for the "JsonValue" to use this feature.
|
||||
### ylong_json Internal architecture diagram
|
||||
![structure](./figure/ylong_json_inner_structure.png)
|
||||
`ylong_json` is mainly divided into two modules, a module with a custom `JsonValue` structure type as the core and a module that ADAPTS to the third-party library `serde`.
|
||||
|
||||
(1) You can create a `JsonValue` instance by:
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use std::str::FromStr;
|
||||
use std::io::Read;
|
||||
use ylong_json::JsonValue;
|
||||
fn create_json_value_instance() {
|
||||
let str: &str = "";
|
||||
// You can use `from_str` to try to generate a `JsonValue` instance from
|
||||
// the &str type.
|
||||
// If the passed &str does not conform to JSON syntax, the corresponding
|
||||
// Error will be returned.
|
||||
let json_value = JsonValue::from_str(str);
|
||||
|
||||
let text: String = String::from("");
|
||||
// You can use `from_text` to generate a `JsonValue` instance from
|
||||
// a series of types that implement AsRef<[u8]>.
|
||||
// If the passed text content does not conform to JSON syntax, the
|
||||
// corresponding Error will be returned.
|
||||
let json_value = JsonValue::from_text(text);
|
||||
|
||||
let path: &str = "";
|
||||
// You can use `from_file` to read a file from corresponding path and
|
||||
// try to generate a `JsonValue` instance.
|
||||
// If the passed path is not valid or the text content does not conform
|
||||
// to JSON syntax, the corresponding Error will be returned.
|
||||
let json_value = JsonValue::from_file(path);
|
||||
|
||||
let mut reader: Box<dyn Read> = Box::new(File::open("").unwrap());
|
||||
// You can use `from_reader` interface to read text from an instance
|
||||
// that implements io::Read and try to generate a `JsonValue` instance.
|
||||
// If the read fails or if the content from the reader does not conform
|
||||
// to JSON syntax, the corresponding Error will be returned.
|
||||
let json_value = JsonValue::from_reader(&mut reader);
|
||||
}
|
||||
1. `JsonValue` is the internal custom structure type of `ylong_json`, and the serialization and deserialization function of `json` is built with this structure as the core.
|
||||
- `JsonValue` : The core structure type, which stores the json content information, has 6 internal enum type variants.
|
||||
- `LinkedList`, `Vec`, `BTreeMap` : Three ways of storing data inside `Array` and `Object`, selected by `features`.
|
||||
- Serialization ability: Supports outputting a `JsonValue` instance as a compact strings or writing to the output stream.
|
||||
- Deserialization ability: Supports parsing `json` text or `json` content in the input stream and generating a `JsonValue` instance.
|
||||
|
||||
2. `ylong_json` adapts to the third-party library `serde`
|
||||
- `Serializer`: The auxiliary structure for serialization.
|
||||
- `Deserializer`: The auxiliary structure for deserialization.
|
||||
- Serialization ability: Supports for serializing a type instance that implements the `serde::Serialize` trait into `json` text content or writing the content to the output stream.
|
||||
- Deserialization ability: If the `json` content has the type that implements `serde::Deserialize` trait, then that part of the `json` content can be deserialized into an instance of that type.
|
||||
|
||||
## Directory
|
||||
```
|
||||
Once the `JsonValue` instance has been successfully created, you can attempt to read and modify the corresponding contents.
|
||||
|
||||
(2) If the type in the JSON text implements the third-party library `serde::Deserialize` trait, you can directly deserialize the text content to an instance of that type.
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use serde::Deserialize;
|
||||
use ylong_json::deserializer::{from_reader, from_slice, from_st};
|
||||
fn deserialize_json_to_instance() {
|
||||
#[derive(Deserialize, PartialEq, Debug)]
|
||||
struct Example {
|
||||
int: u32,
|
||||
seq: Vec<String>,
|
||||
tup: (i32, i32, i32),
|
||||
}
|
||||
|
||||
// You can use `from_str` to try to generate an instance from String.
|
||||
// If the passed String does not conform to JSON syntax, the corresponding
|
||||
// Error will be returned.
|
||||
let str = r#"{"int":1,"seq":["abcd","efgh"],"tup":[1,2,3]}"#;
|
||||
let example = from_str::<Example>(str).unwrap();
|
||||
|
||||
// You can use `from_slice` to try to generate an instance from &u8.
|
||||
// If the passed &u8 does not conform to JSON syntax, the corresponding
|
||||
// Error will be returned.
|
||||
let slice = str.as_bytes();
|
||||
let example = from_slice::<Example>(slice).unwrap();
|
||||
|
||||
// You can use `from_reader` to try to generate an instance from
|
||||
// locations, files, io streams, and so on that implement io::Write.
|
||||
// If the passed text content does not conform to JSON syntax,
|
||||
// the corresponding Error will be returned.
|
||||
let mut file: File = File::open("./example.txt").unwrap();
|
||||
let example = from_reader::<Example>(file).unwrap();
|
||||
}
|
||||
```
|
||||
|
||||
### Function 2: Reads and modifies a key-value pair
|
||||
After a `JsonValue` instance is successfully generated, you can use a subscript to find the corresponding key-value pair (to obtain a common reference to the corresponding `JsonValue`).
|
||||
|
||||
A subscript of type &str or String can be used to find a key-value pair in Object;
|
||||
A Subscript of type usize can be used to find a key-value pair in an Array.
|
||||
```rust
|
||||
use std::str::FromStr;
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
// JSON string for the example
|
||||
const JSON_TEXT: &str = r#"
|
||||
{
|
||||
"key": "value",
|
||||
"array": [1, 2, 3]
|
||||
}
|
||||
"#;
|
||||
|
||||
fn find_key_value_pair() {
|
||||
// Creates a JsonValue instance from the example string, the syntax is
|
||||
// correct so the parse must succeed here, so uses unwrap.
|
||||
let json_value = JsonValue::from_str(JSON_TEXT).unwrap();
|
||||
|
||||
// Since json is itself a table, you can use the &str type to obtain
|
||||
// a common reference to the internal value.
|
||||
let value: &JsonValue = &json_value["key"];
|
||||
|
||||
// You can use the &str type to obtain a common reference to the "array" member, and
|
||||
// then use the usize type to obtain a common reference to the corresponding element.
|
||||
let array_item: &JsonValue = &json_value["array"][0];
|
||||
|
||||
// If you try to find a key that does not exist in a table,
|
||||
// `&JsonValue::Null` will be returned.
|
||||
let no_such_key: &JsonValue = &json_value["no_such_key"];
|
||||
|
||||
// When searching for the Array type, if the subscript exceeds the Array length,
|
||||
// `&JsonValue::Null` will also be returned.
|
||||
let no_such_index: &JsonValue = &json_value["array"][100];
|
||||
|
||||
// If you use a subscript to visit `JsonValue` types other than Object and Array,
|
||||
// `&JsonValue::Null` will also be returned.
|
||||
let invalid_index: &JsonValue = &json_value["key"]["invalid"];
|
||||
let invalid_index: &JsonValue = &json_value["key"][0];
|
||||
}
|
||||
```
|
||||
You can also use the same method to obtain a mutable reference to `JsonValue`.
|
||||
After obtaining the mutable reference, you can modify it, but you need to make sure that it conforms to JSON syntax.
|
||||
```rust
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
// JSON string for the example
|
||||
const JSON_TEXT: &str = r#"
|
||||
{
|
||||
"key": "value",
|
||||
"array": [1, 2, 3]
|
||||
}
|
||||
"#;
|
||||
|
||||
fn modify_key_value_pair() {
|
||||
// Creates a JsonValue instance from the example string, the syntax is
|
||||
// correct so the parse must succeed here, so uses unwrap.
|
||||
// Here the JSON instance needs to be mutable because you need to obtain a mutable reference.
|
||||
let mut json_value = JsonValue::from_str(JSON_TEXT).unwrap();
|
||||
|
||||
// Obtains a mutable reference to the member by "key" and set it to the number 123.
|
||||
// In the libraty, many primitive types implement conversion from themselves to JsonValue,
|
||||
// so they can be converted to `JsonValue` by using `into()` method.
|
||||
// After executing this code, the contents of the table are as follows:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [1, 2, 3]
|
||||
// }
|
||||
json_value["key"] = 123_i32.into();
|
||||
|
||||
// Obtains a mutable reference to the member by using "array" and the subscript 0,
|
||||
// and set it to the number 123.
|
||||
// After executing this code, the contents of the table are as follows:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [123, 2, 3]
|
||||
// }
|
||||
json_value["array"][0] = 123_i32.into();
|
||||
|
||||
// If you try to obtain a mutable reference to a key that does not exist in the table,
|
||||
// then the key will be inserted in the table with the corresponding value JsonValue::Null,
|
||||
// and changes the value baesd on that.
|
||||
// After executing this code, the json_value member "no_such_key" has been added,
|
||||
// and the value is 123.
|
||||
// The contents of the table are as follows:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [123, 2, 3],
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["no_such_key"] = 123_i32.into();
|
||||
|
||||
// When trying to obtain a mutable reference to a member of the Array type, if the
|
||||
// subscript exceeds the Array length, then a `JsonValue::Null` will be added at
|
||||
// the end of the Array and will return a mutable reference to that position.
|
||||
// After executing this code, the length of the array member of `json_value` becomes 4,
|
||||
// and the value of the last member is 123.
|
||||
// The contents of the table are as follows:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [123, 2, 3, 123],
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["array"][100] = 123_i32.into();
|
||||
|
||||
// When using a subscript of &str type or String type to obtain a mutable reference to
|
||||
// a non-Object type, will replace the value with an empty Object and then visit it with
|
||||
// that subscript.
|
||||
// After executing this code, the array member of `json_value` becomes of type Object
|
||||
// and contains a key-value pair: "key" => 123.
|
||||
// The contents of the table are as follows:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": {
|
||||
// "key": 123
|
||||
// },
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["array"]["key"] = 123_i32.into();
|
||||
|
||||
// When using a subscript of usize type to obtain a mutable reference to a non-Array
|
||||
// type, will replace the value with an empty Array and then visit it with that subscript.
|
||||
// After executing this code, the key member of `json_value` becomes of type Array,
|
||||
// and contains a member: key[0] => 123.
|
||||
// The contents of the table are as follows:
|
||||
// {
|
||||
// "key": [123],
|
||||
// "array": {
|
||||
// "key": 123
|
||||
// },
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["key"][0] = 123_i32.into();
|
||||
}
|
||||
```
|
||||
|
||||
### Function 3: Outputs JSON text
|
||||
(1) When you have a JsonValue instance, you can convert it to text and output it to a specified location: string, file, network, etc.
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
fn output_json_text(json_value: JsonValue) {
|
||||
// Uses `to_compact_string()` to output the `json_value` as a string.
|
||||
let string = json_value.to_compact_string().unwrap();
|
||||
|
||||
// Uses `compact_encode()` to output JSON text to a specified location,
|
||||
// file, io stream, etc., which implements io::Write.
|
||||
let mut file: File = File::open("").unwrap();
|
||||
let _ = json_value.compact_encode(&mut file);
|
||||
}
|
||||
```
|
||||
Because there is no strong order requirement for JSON internal elements,
|
||||
the output order of members will have a certain randomness,
|
||||
but it does not affect the semantics of JSON text.
|
||||
|
||||
(2) You can also serialize an instance of a type that implements the `serde::Serialize` trait to JSON text.
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use serde::Serialize;
|
||||
use ylong_json::serializer_compact::{to_string, to_writer};
|
||||
|
||||
fn<V: Serialize> output_json_text(value: V) {
|
||||
#[derive(Serialize)]
|
||||
struct Exmaple {
|
||||
int: u32,
|
||||
seq: Vec<&'static str>,
|
||||
tup: (i32, i32, i32),
|
||||
}
|
||||
|
||||
let example = Example {
|
||||
int: 1,
|
||||
seq: vec!["a", "b"],
|
||||
tup: (1, 2, 3),
|
||||
};
|
||||
|
||||
// Uses `to_string()` to output the value as a string.
|
||||
let string = to_string(&example).unwrap();
|
||||
|
||||
// Uses `to_writer()` to output JSON text to a specified location,
|
||||
// file, io stream, etc., which implements io::Write.
|
||||
let mut file: File = File::open("./example.txt").unwrap();
|
||||
let _ = to_writer(&example, &mut file);
|
||||
}
|
||||
ylong_json
|
||||
├─ examples # ylong_json code example
|
||||
├─ include # ylong_json.h
|
||||
├─ src
|
||||
│ ├─ value # Array and Object type definitions and related methods
|
||||
│ ├─ adapter.rs # Adapts to the C interface implementation
|
||||
│ ├─ consts.rs # Some definitions of constants and tables
|
||||
│ ├─ deserializer.rs # Deserialization implementation of the adaptation serde
|
||||
│ ├─ encoder.rs # Serialization implementation for the `JsonValue` type
|
||||
│ ├─ error.rs # Error type definition, helpful to identify the problem
|
||||
│ ├─ link_list.rs # LinkedList type definition and related methods
|
||||
│ ├─ serializer_compact.rs # Serialization implementation of the adaptation serde
|
||||
│ ├─ states.rs # Deserialization implementation for the `JsonValue` type
|
||||
│ └─ value.rs # JsonValue type definition and related methods
|
||||
└─ tests # Test directory
|
||||
```
|
||||
|
||||
## Build
|
||||
@ -284,6 +58,9 @@ deps += ["//example_path/ylong_json:lib"]
|
||||
ylong_json = { path = "/example_path/ylong_json" } # Uses path dependencies.
|
||||
```
|
||||
|
||||
## User Guide
|
||||
See [user_guide](./docs/user_guide.md)
|
||||
|
||||
## Performance test
|
||||
```
|
||||
1.Test environment
|
||||
@ -322,21 +99,3 @@ MemTotal: 16G
|
||||
| example4 | 18,461 ns/iter | 12,471 ns/iter |
|
||||
```
|
||||
|
||||
## Directory
|
||||
```
|
||||
ylong_json
|
||||
├─ examples # ylong_json code example
|
||||
├─ include # ylong_json.h
|
||||
├─ src
|
||||
│ ├─ value # Array and Object type definitions and related methods
|
||||
│ ├─ adapter.rs # Adapts to the C interface implementation
|
||||
│ ├─ consts.rs # Some definitions of constants and tables
|
||||
│ ├─ deserializer.rs # Deserialization implementation of the adaptation serde
|
||||
│ ├─ encoder.rs # Serialization implementation for the `JsonValue` type
|
||||
│ ├─ error.rs # Error type definition, helpful to identify the problem
|
||||
│ ├─ link_list.rs # LinkedList type definition and related methods
|
||||
│ ├─ serializer_compact.rs # Serialization implementation of the adaptation serde
|
||||
│ ├─ states.rs # Deserialization implementation for the `JsonValue` type
|
||||
│ └─ value.rs # JsonValue type definition and related methods
|
||||
└─ tests # Test directory
|
||||
```
|
286
README_zh.md
286
README_zh.md
@ -1,240 +1,47 @@
|
||||
# ylong_json
|
||||
|
||||
## 简介
|
||||
|
||||
`ylong_json` 模块提供了 JSON 语法格式文本或字符串的序列化功能,以及对应生成实例的反序列化功能。
|
||||
|
||||
`ylong_json` 包含以下核心功能:
|
||||
### ylong_json 在 Openharmony 中的位置
|
||||
![structure](./figure/ylong_json_oh_relate.png)
|
||||
以下是对于上图关键字段的描述信息:
|
||||
- `ylong_json`:提供 `json` 序列化与反序列化能力的系统组件
|
||||
- `serde`:第三方库,用于高效、通用地序列化和反序列化 `Rust` 数据结构。
|
||||
|
||||
### 功能一:生成 JSON 实例
|
||||
`ylong_json` 提供了从 JSON 文本或字符串生成一个 `JsonValue` 实例的功能。
|
||||
### ylong_json 内部架构图
|
||||
![structure](./figure/ylong_json_inner_structure.png)
|
||||
`ylong_json` 内部主要分为两个模块,以自定义 `JsonValue` 类型为核心的模块和适配第三方库 `serde` 的模块。
|
||||
|
||||
(1)可以通过以下方法创建 `JsonValue` 实例:
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use std::str::FromStr;
|
||||
use std::io::Read;
|
||||
use ylong_json::JsonValue;
|
||||
1. `JsonValue` 是 `ylong_json` 内部自定义的结构类型,以该结构为核心构建 `json` 的序列化与反序列化功能。
|
||||
- `JsonValue` :核心结构类型,存储 `json` 内容信息,共有 6 种枚举类型变体。
|
||||
- `LinkedList`, `Vec`, `BTreeMap`:`Array` 与 `Object` 内部数据存储的三种方式,通过 `features` 选择。
|
||||
- 序列化功能:支持将 `JsonValue` 实例输出为紧凑型字符串或写到输出流中。
|
||||
- 反序列化功能:支持解析 `json` 文本或输入流中的 `json` 内容并生成 `JsonValue` 实例。
|
||||
|
||||
fn create_json_value_instance() {
|
||||
let str: &str = "";
|
||||
// 可以使用 from_str 接口,从 &str 类型尝试生成 JsonValue 实例。
|
||||
// 如果传入的 &str 不符合 JSON 语法,会返回对应的 Error。
|
||||
let json_value = JsonValue::from_str(str);
|
||||
|
||||
let text: String = String::from("");
|
||||
// 可以使用 from_text 接口,从一系列实现 AsRef<[u8]> 的类型生成 JsonValue 实例。
|
||||
// 如果传入的文本内容不符合 JSON 语法,会返回对应的 Error。
|
||||
let json_value = JsonValue::from_text(text);
|
||||
|
||||
let path: &str = "";
|
||||
// 可以使用 from_file 接口,从对应路径的文件读取内容,并尝试生成 JsonValue 实例。
|
||||
// 如果传入的 path 不合法或者文本内容不符合 JSON 语法,会返回对应的 Error。
|
||||
let json_value = JsonValue::from_file(path);
|
||||
|
||||
let mut reader: Box<dyn Read> = Box::new(File::open("").unwrap());
|
||||
// 可以使用 from_reader 接口,从实现了 io::Read 的实例中读取文本,并尝试生成 JsonValue 实例。
|
||||
// 如果读取失败或者从 reader 中读取的内容不符合 JSON 语法,会返回对应的 Error。
|
||||
let json_value = JsonValue::from_reader(&mut reader);
|
||||
}
|
||||
2. `ylong_json` 适配了第三方库 `serde`
|
||||
- `Serializer`:序列化输出的辅助结构类型。
|
||||
- `Deserializer`:反序列化输出的辅助结构类型。
|
||||
- 序列化功能:支持将实现了 `serde::Serialize` trait 的类型实例序列化为 `json` 文本内容或将内容写到输出流中。
|
||||
- 反序列化功能:若实现了 `serde::Deserialize` trait 的类型在 `json` 内容中,则可将该部分 `json` 内容反序列化为该类型的实例。
|
||||
|
||||
## 目录
|
||||
```
|
||||
当 `JsonValue` 实例创建成功后,就可以尝试读取和修改对应的内容了。
|
||||
|
||||
(2)如果 JSON 文本中的类型实现了第三方库 `serde::Deserialize` trait,则可以直接将文本内容反序列化为该类型的实例。
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use serde::Deserialize;
|
||||
use ylong_json::deserializer::{from_reader, from_slice, from_st};
|
||||
fn deserialize_json_to_instance() {
|
||||
#[derive(Deserialize, PartialEq, Debug)]
|
||||
struct Example {
|
||||
int: u32,
|
||||
seq: Vec<String>,
|
||||
tup: (i32, i32, i32),
|
||||
}
|
||||
|
||||
// 可以使用 from_str 接口,从 &str 类型生成实例。
|
||||
// 如果传入的 &str 不符合 JSON 语法,会返回对应的 Error。
|
||||
let tr = r#"{"int":1,"seq":["abcd","efgh"],"tup":[1,2,3]}"#;
|
||||
let example = from_str::<Example>(str).unwrap();
|
||||
|
||||
// 可以使用 from_slice 接口,从 &u8 类型生成实例。
|
||||
// 如果传入的 &u8 不符合 JSON 语法,会返回对应的 Error。
|
||||
let slice = str.as_bytes();
|
||||
let example = from_slice::<Example>(slice).unwrap();
|
||||
|
||||
|
||||
// 可以使用 from_reader 接口,从实现了 io::Write 的位置、文件、io流等生成实例。
|
||||
// 如果传入的文本内容不符合 JSON 语法,会返回对应的 Error。
|
||||
let mut file: File = File::open("./example.txt").unwrap();
|
||||
let example = from_reader::<Example>(file).unwrap();
|
||||
}
|
||||
```
|
||||
|
||||
### 功能二:读取、修改键值对
|
||||
`JsonValue` 实例生成成功后,可以通过各种下标来查找对应的键值对(获取到对应 `JsonValue` 的普通引用)。
|
||||
|
||||
&str 和 String 类型的下标可以用于查找 Object 内的键值对;usize 类型的下标可以用于查找 Array 内的键值对。
|
||||
```rust
|
||||
use std::str::FromStr;
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
// 示例的 JSON 字符串
|
||||
const JSON_TEXT: &str = r#"
|
||||
{
|
||||
"key": "value",
|
||||
"array": [1, 2, 3]
|
||||
}
|
||||
"#;
|
||||
|
||||
fn find_key_value_pair() {
|
||||
// 根据示例字符串创建 JsonValue 实例,语法正确所以此处解析必定成功,使用 unwrap。
|
||||
let json_value = JsonValue::from_str(JSON_TEXT).unwrap();
|
||||
|
||||
// 由于 json 本身也是一个表,所以可以使用 &str 类型获取内部值的普通引用。
|
||||
let value: &JsonValue = &json_value["key"];
|
||||
|
||||
// 可以通过 &str 类型先获取到 “array” 成员的普通引用,再根据 usize 类型获取对应元素的普通引用。
|
||||
let array_item: &JsonValue = &json_value["array"][0];
|
||||
|
||||
// 如果尝试查找一个不存在表中的键,会返回 &JsonValue::Null。
|
||||
let no_such_key: &JsonValue = &json_value["no_such_key"];
|
||||
|
||||
// 对 Array 类型查找时,若下标超过 Array 长度,也会返回 &JsonValue::Null。
|
||||
let no_such_index: &JsonValue = &json_value["array"][100];
|
||||
|
||||
// 对一个 Object 和 Array 类型以外的 JsonValue 类型使用下标访问也会返回 &JsonValue::Null。
|
||||
let invalid_index: &JsonValue = &json_value["key"]["invalid"];
|
||||
let invalid_index: &JsonValue = &json_value["key"][0];
|
||||
}
|
||||
```
|
||||
也可以通过相同方法获取到对应 `JsonValue` 的可变引用,获取到可变引用后可以对其进行修改,修改时需要注意符合 JSON 语法。
|
||||
```rust
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
// 示例的 JSON 字符串
|
||||
const JSON_TEXT: &str = r#"
|
||||
{
|
||||
"key": "value",
|
||||
"array": [1, 2, 3]
|
||||
}
|
||||
"#;
|
||||
|
||||
fn modify_key_value_pair() {
|
||||
// 根据示例字符串创建 JsonValue 实例,语法正确所以此处解析必定成功,使用 unwrap。
|
||||
// 此处由于需要获取可变引用,JSON 实例需要可变。
|
||||
let mut json_value = JsonValue::from_str(JSON_TEXT).unwrap();
|
||||
|
||||
// 通过 “key” 获取到对应成员的可变引用,并将其设置为数值 123。
|
||||
// 库中给许多基本类型实现了从自身到 JsonValue 的转换,所以可以通过 into() 方法转换为 JsonValue。
|
||||
// 执行此句代码后,表中内容如下:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [1, 2, 3]
|
||||
// }
|
||||
json_value["key"] = 123_i32.into();
|
||||
|
||||
// 通过 “array” 和下标 0 获取到对应成员的可变引用,并将其设置为数值 123。
|
||||
// 执行此句代码后,表中内容如下:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [123, 2, 3]
|
||||
// }
|
||||
json_value["array"][0] = 123_i32.into();
|
||||
|
||||
// 如果尝试获取一个不存在表中的键的可变引用,会在表中插入该键且对应值为 JsonValue::Null,并在此基础上进行修改。
|
||||
// 执行此行代码后,json_value 中会增加一个成员 “no_such_key”,且值为数值 123。
|
||||
// 表中内容如下:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [123, 2, 3],
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["no_such_key"] = 123_i32.into();
|
||||
|
||||
// 对 Array 类型的成员尝试获取可变引用时,若下标超过 Array 长度,
|
||||
// 会在 Array 末尾插入一个 JsonValue::Null,并返回该位置的可变引用。
|
||||
// 执行此行代码后,json_value 的 “array” 成员的长度变为 4。
|
||||
// 表中内容如下:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [123, 2, 3, 123],
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["array"][100] = 123_i32.into();
|
||||
|
||||
// 对一个非 Object 类型使用 &str 类型或 String 下标获取可变引用时,
|
||||
// 会将该值替换为一个空 Object,然后再用此下标对其进行访问。
|
||||
// 执行此代码后,json_value 的 array 成员变成 Object 类型,且含有一个键值对:“key” => 123。
|
||||
// 表中内容如下:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": {
|
||||
// "key": 123
|
||||
// },
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["array"]["key"] = 123_i32.into();
|
||||
|
||||
// 对一个非 Array 类型使用 usize 类型下标获取可变引用时,
|
||||
// 会将该值替换成一个空 Array,然后再用此下标对其进行访问。
|
||||
// 执行此代码后,json_value 的 key 成员变成 Array 类型,且含有一个成员: key[0] => 123
|
||||
// 表中内容如下:
|
||||
// {
|
||||
// "key": [123],
|
||||
// "array": {
|
||||
// "key": 123
|
||||
// },
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["key"][0] = 123_i32.into();
|
||||
}
|
||||
```
|
||||
|
||||
### 功能三:输出 JSON 文本
|
||||
(1)当拥有一个 `JsonValue` 实例时,可以将该 `JsonValue` 实例转化成文本并输出到指定位置:字符串、文件、网络等。
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
fn output_json_text(json_value: JsonValue) {
|
||||
// 使用 to_compact_string() 接口将 json_value 输出成一个字符串。
|
||||
let string = json_value.to_compact_string().unwrap();
|
||||
|
||||
// 使用 compact_encode() 接口将 JSON 文本输出到指定实现了 io::Write 的位置,文件、io流等。
|
||||
let mut file: File = File::open("").unwrap();
|
||||
let _ = json_value.compact_encode(&mut file);
|
||||
}
|
||||
```
|
||||
由于 JSON 内部元素没有较强的顺序要求,所以成员的输出顺序会有一定随机性,但是不影响 JSON 文本的语义。
|
||||
|
||||
(2)可以将一个实现了第三方库 `serde::Serialize` trait 的类型实例序列化为 JSON 文本。
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use serde::Serialize;
|
||||
use ylong_json::serializer_compact::{to_string, to_writer};
|
||||
|
||||
fn output_json_text() {
|
||||
#[derive(Serialize)]
|
||||
struct Exmaple {
|
||||
int: u32,
|
||||
seq: Vec<&'static str>,
|
||||
tup: (i32, i32, i32),
|
||||
}
|
||||
|
||||
let example = Example {
|
||||
int: 1,
|
||||
seq: vec!["a", "b"],
|
||||
tup: (1, 2, 3),
|
||||
};
|
||||
|
||||
// 使用 to_string() 接口将 value 输出成一个字符串。
|
||||
let string = to_string(&example).unwrap();
|
||||
|
||||
// 使用 to_writer() 接口将 JSON 文本输出到指定实现了 io::Write 的位置,文件、io流等。
|
||||
let mut file: File = File::open("./example.txt").unwrap();
|
||||
let _ = to_writer(&example, &mut file);
|
||||
}
|
||||
ylong_json
|
||||
├─ examples # ylong_json 代码示例
|
||||
├─ include # ylong_json.h
|
||||
├─ src
|
||||
│ ├─ value # Array, Object 类型定义和相关方法实现
|
||||
│ ├─ adapter.rs # 适配 C 的接口实现
|
||||
│ ├─ consts.rs # 一些常数与表格的定义
|
||||
│ ├─ deserializer.rs # 适配 serde 的反序列化实现
|
||||
│ ├─ encoder.rs # 为 JsonValue 类型序列化实现
|
||||
│ ├─ error.rs # 错误类型定义,便于定位
|
||||
│ ├─ link_list.rs # LinkedList 类型定义和相关方法实现
|
||||
│ ├─ serializer_compact.rs # 适配 serde 的序列化实现
|
||||
│ ├─ states.rs # 为 JsonValue 类型反序列化实现
|
||||
│ └─ value.rs # JsonValue 类型定义和相关方法实现
|
||||
└─ tests # 测试目录
|
||||
```
|
||||
|
||||
## 编译构建
|
||||
@ -251,6 +58,9 @@ deps += ["//example_path/ylong_json:lib"]
|
||||
ylong_json = { path = "/example_path/ylong_json" } # 请使用路径依赖
|
||||
```
|
||||
|
||||
## 用户指南
|
||||
详情内容请见[用户指南](./docs/user_guide_zh.md)
|
||||
|
||||
## 性能测试
|
||||
```
|
||||
1.测试环境
|
||||
@ -288,23 +98,3 @@ CPU 核心数:8
|
||||
| example3 | 55,910 ns/iter | 59,717 ns/iter |
|
||||
| example4 | 18,461 ns/iter | 12,471 ns/iter |
|
||||
```
|
||||
|
||||
## 目录
|
||||
|
||||
```
|
||||
ylong_json
|
||||
├─ examples # ylong_json 代码示例
|
||||
├─ include # ylong_json.h
|
||||
├─ src
|
||||
│ ├─ value # Array, Object 类型定义和相关方法实现
|
||||
│ ├─ adapter.rs # 适配 C 的接口实现
|
||||
│ ├─ consts.rs # 一些常数与表格的定义
|
||||
│ ├─ deserializer.rs # 适配 serde 的反序列化实现
|
||||
│ ├─ encoder.rs # 为 JsonValue 类型序列化实现
|
||||
│ ├─ error.rs # 错误类型定义,便于定位
|
||||
│ ├─ link_list.rs # LinkedList 类型定义和相关方法实现
|
||||
│ ├─ serializer_compact.rs # 适配 serde 的序列化实现
|
||||
│ ├─ states.rs # 为 JsonValue 类型反序列化实现
|
||||
│ └─ value.rs # JsonValue 类型定义和相关方法实现
|
||||
└─ tests # 测试目录
|
||||
```
|
5
RELEASE_NOTE.md
Normal file
5
RELEASE_NOTE.md
Normal file
@ -0,0 +1,5 @@
|
||||
# 1.0.0
|
||||
1. ylong_json initial version, which provides these features:
|
||||
- serialize: output JSON text or string from `JsonValue`.
|
||||
- deserialize: generate an instance of `JsonValue` from JSON text or string.
|
||||
- serde: serialize or deserialize for a struct which implements the serde trait
|
269
docs/user_guide.md
Normal file
269
docs/user_guide.md
Normal file
@ -0,0 +1,269 @@
|
||||
# ylong_json User Guide
|
||||
|
||||
The `ylong_json` module provides serialization of text or string in JSON syntax format, and deserialization of corresponding generated instances. In addition, the `ylong_json` module also adapts to the third-party library `serde`. Structures that implement specific traits in the `serde` library can be serialized and deserialized.
|
||||
|
||||
If you need to see the detailed interface description, please check the docs of the corresponding interface. You can use `cargo doc --open` to generate and view the docs.
|
||||
|
||||
### Function 1: Generates a JSON instance
|
||||
`ylong_json` provides the ability to generate an instance of `JsonValue` from JSON text or string. You need to use a series of instance creation methods for the "JsonValue" to use this feature.
|
||||
|
||||
(1) You can create a `JsonValue` instance by:
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use std::str::FromStr;
|
||||
use std::io::Read;
|
||||
use ylong_json::JsonValue;
|
||||
fn create_json_value_instance() {
|
||||
let str: &str = "";
|
||||
// You can use `from_str` to try to generate a `JsonValue` instance from
|
||||
// the &str type.
|
||||
// If the passed &str does not conform to JSON syntax, the corresponding
|
||||
// Error will be returned.
|
||||
let json_value = JsonValue::from_str(str);
|
||||
|
||||
let text: String = String::from("");
|
||||
// You can use `from_text` to generate a `JsonValue` instance from
|
||||
// a series of types that implement AsRef<[u8]>.
|
||||
// If the passed text content does not conform to JSON syntax, the
|
||||
// corresponding Error will be returned.
|
||||
let json_value = JsonValue::from_text(text);
|
||||
|
||||
let path: &str = "";
|
||||
// You can use `from_file` to read a file from corresponding path and
|
||||
// try to generate a `JsonValue` instance.
|
||||
// If the passed path is not valid or the text content does not conform
|
||||
// to JSON syntax, the corresponding Error will be returned.
|
||||
let json_value = JsonValue::from_file(path);
|
||||
|
||||
let mut reader: Box<dyn Read> = Box::new(File::open("").unwrap());
|
||||
// You can use `from_reader` interface to read text from an instance
|
||||
// that implements io::Read and try to generate a `JsonValue` instance.
|
||||
// If the read fails or if the content from the reader does not conform
|
||||
// to JSON syntax, the corresponding Error will be returned.
|
||||
let json_value = JsonValue::from_reader(&mut reader);
|
||||
}
|
||||
```
|
||||
Once the `JsonValue` instance has been successfully created, you can attempt to read and modify the corresponding contents.
|
||||
|
||||
(2) If the type in the JSON text implements the third-party library `serde::Deserialize` trait, you can directly deserialize the text content to an instance of that type.
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use serde::Deserialize;
|
||||
use ylong_json::deserializer::{from_reader, from_slice, from_st};
|
||||
fn deserialize_json_to_instance() {
|
||||
#[derive(Deserialize, PartialEq, Debug)]
|
||||
struct Example {
|
||||
int: u32,
|
||||
seq: Vec<String>,
|
||||
tup: (i32, i32, i32),
|
||||
}
|
||||
|
||||
// You can use `from_str` to try to generate an instance from String.
|
||||
// If the passed String does not conform to JSON syntax, the corresponding
|
||||
// Error will be returned.
|
||||
let str = r#"{"int":1,"seq":["abcd","efgh"],"tup":[1,2,3]}"#;
|
||||
let example = from_str::<Example>(str).unwrap();
|
||||
|
||||
// You can use `from_slice` to try to generate an instance from &u8.
|
||||
// If the passed &u8 does not conform to JSON syntax, the corresponding
|
||||
// Error will be returned.
|
||||
let slice = str.as_bytes();
|
||||
let example = from_slice::<Example>(slice).unwrap();
|
||||
|
||||
// You can use `from_reader` to try to generate an instance from
|
||||
// locations, files, io streams, and so on that implement io::Write.
|
||||
// If the passed text content does not conform to JSON syntax,
|
||||
// the corresponding Error will be returned.
|
||||
let mut file: File = File::open("./example.txt").unwrap();
|
||||
let example = from_reader::<Example>(file).unwrap();
|
||||
}
|
||||
```
|
||||
|
||||
### Function 2: Reads and modifies a key-value pair
|
||||
After a `JsonValue` instance is successfully generated, you can use a subscript to find the corresponding key-value pair (to obtain a common reference to the corresponding `JsonValue`).
|
||||
|
||||
A subscript of type &str or String can be used to find a key-value pair in Object;
|
||||
A Subscript of type usize can be used to find a key-value pair in an Array.
|
||||
```rust
|
||||
use std::str::FromStr;
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
// JSON string for the example
|
||||
const JSON_TEXT: &str = r#"
|
||||
{
|
||||
"key": "value",
|
||||
"array": [1, 2, 3]
|
||||
}
|
||||
"#;
|
||||
|
||||
fn find_key_value_pair() {
|
||||
// Creates a JsonValue instance from the example string, the syntax is
|
||||
// correct so the parse must succeed here, so uses unwrap.
|
||||
let json_value = JsonValue::from_str(JSON_TEXT).unwrap();
|
||||
|
||||
// Since json is itself a table, you can use the &str type to obtain
|
||||
// a common reference to the internal value.
|
||||
let value: &JsonValue = &json_value["key"];
|
||||
|
||||
// You can use the &str type to obtain a common reference to the "array" member, and
|
||||
// then use the usize type to obtain a common reference to the corresponding element.
|
||||
let array_item: &JsonValue = &json_value["array"][0];
|
||||
|
||||
// If you try to find a key that does not exist in a table,
|
||||
// `&JsonValue::Null` will be returned.
|
||||
let no_such_key: &JsonValue = &json_value["no_such_key"];
|
||||
|
||||
// When searching for the Array type, if the subscript exceeds the Array length,
|
||||
// `&JsonValue::Null` will also be returned.
|
||||
let no_such_index: &JsonValue = &json_value["array"][100];
|
||||
|
||||
// If you use a subscript to visit `JsonValue` types other than Object and Array,
|
||||
// `&JsonValue::Null` will also be returned.
|
||||
let invalid_index: &JsonValue = &json_value["key"]["invalid"];
|
||||
let invalid_index: &JsonValue = &json_value["key"][0];
|
||||
}
|
||||
```
|
||||
You can also use the same method to obtain a mutable reference to `JsonValue`.
|
||||
After obtaining the mutable reference, you can modify it, but you need to make sure that it conforms to JSON syntax.
|
||||
```rust
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
// JSON string for the example
|
||||
const JSON_TEXT: &str = r#"
|
||||
{
|
||||
"key": "value",
|
||||
"array": [1, 2, 3]
|
||||
}
|
||||
"#;
|
||||
|
||||
fn modify_key_value_pair() {
|
||||
// Creates a JsonValue instance from the example string, the syntax is
|
||||
// correct so the parse must succeed here, so uses unwrap.
|
||||
// Here the JSON instance needs to be mutable because you need to obtain a mutable reference.
|
||||
let mut json_value = JsonValue::from_str(JSON_TEXT).unwrap();
|
||||
|
||||
// Obtains a mutable reference to the member by "key" and set it to the number 123.
|
||||
// In the libraty, many primitive types implement conversion from themselves to JsonValue,
|
||||
// so they can be converted to `JsonValue` by using `into()` method.
|
||||
// After executing this code, the contents of the table are as follows:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [1, 2, 3]
|
||||
// }
|
||||
json_value["key"] = 123_i32.into();
|
||||
|
||||
// Obtains a mutable reference to the member by using "array" and the subscript 0,
|
||||
// and set it to the number 123.
|
||||
// After executing this code, the contents of the table are as follows:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [123, 2, 3]
|
||||
// }
|
||||
json_value["array"][0] = 123_i32.into();
|
||||
|
||||
// If you try to obtain a mutable reference to a key that does not exist in the table,
|
||||
// then the key will be inserted in the table with the corresponding value JsonValue::Null,
|
||||
// and changes the value baesd on that.
|
||||
// After executing this code, the json_value member "no_such_key" has been added,
|
||||
// and the value is 123.
|
||||
// The contents of the table are as follows:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [123, 2, 3],
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["no_such_key"] = 123_i32.into();
|
||||
|
||||
// When trying to obtain a mutable reference to a member of the Array type, if the
|
||||
// subscript exceeds the Array length, then a `JsonValue::Null` will be added at
|
||||
// the end of the Array and will return a mutable reference to that position.
|
||||
// After executing this code, the length of the array member of `json_value` becomes 4,
|
||||
// and the value of the last member is 123.
|
||||
// The contents of the table are as follows:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [123, 2, 3, 123],
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["array"][100] = 123_i32.into();
|
||||
|
||||
// When using a subscript of &str type or String type to obtain a mutable reference to
|
||||
// a non-Object type, will replace the value with an empty Object and then visit it with
|
||||
// that subscript.
|
||||
// After executing this code, the array member of `json_value` becomes of type Object
|
||||
// and contains a key-value pair: "key" => 123.
|
||||
// The contents of the table are as follows:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": {
|
||||
// "key": 123
|
||||
// },
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["array"]["key"] = 123_i32.into();
|
||||
|
||||
// When using a subscript of usize type to obtain a mutable reference to a non-Array
|
||||
// type, will replace the value with an empty Array and then visit it with that subscript.
|
||||
// After executing this code, the key member of `json_value` becomes of type Array,
|
||||
// and contains a member: key[0] => 123.
|
||||
// The contents of the table are as follows:
|
||||
// {
|
||||
// "key": [123],
|
||||
// "array": {
|
||||
// "key": 123
|
||||
// },
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["key"][0] = 123_i32.into();
|
||||
}
|
||||
```
|
||||
|
||||
### Function 3: Outputs JSON text
|
||||
(1) When you have a JsonValue instance, you can convert it to text and output it to a specified location: string, file, network, etc.
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
fn output_json_text(json_value: JsonValue) {
|
||||
// Uses `to_compact_string()` to output the `json_value` as a string.
|
||||
let string = json_value.to_compact_string().unwrap();
|
||||
|
||||
// Uses `compact_encode()` to output JSON text to a specified location,
|
||||
// file, io stream, etc., which implements io::Write.
|
||||
let mut file: File = File::open("").unwrap();
|
||||
let _ = json_value.compact_encode(&mut file);
|
||||
}
|
||||
```
|
||||
Because there is no strong order requirement for JSON internal elements,
|
||||
the output order of members will have a certain randomness,
|
||||
but it does not affect the semantics of JSON text.
|
||||
|
||||
(2) You can also serialize an instance of a type that implements the `serde::Serialize` trait to JSON text.
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use serde::Serialize;
|
||||
use ylong_json::serializer_compact::{to_string, to_writer};
|
||||
|
||||
fn<V: Serialize> output_json_text(value: V) {
|
||||
#[derive(Serialize)]
|
||||
struct Exmaple {
|
||||
int: u32,
|
||||
seq: Vec<&'static str>,
|
||||
tup: (i32, i32, i32),
|
||||
}
|
||||
|
||||
let example = Example {
|
||||
int: 1,
|
||||
seq: vec!["a", "b"],
|
||||
tup: (1, 2, 3),
|
||||
};
|
||||
|
||||
// Uses `to_string()` to output the value as a string.
|
||||
let string = to_string(&example).unwrap();
|
||||
|
||||
// Uses `to_writer()` to output JSON text to a specified location,
|
||||
// file, io stream, etc., which implements io::Write.
|
||||
let mut file: File = File::open("./example.txt").unwrap();
|
||||
let _ = to_writer(&example, &mut file);
|
||||
}
|
||||
```
|
235
docs/user_guide_zh.md
Normal file
235
docs/user_guide_zh.md
Normal file
@ -0,0 +1,235 @@
|
||||
# ylong_json 用户指南
|
||||
|
||||
`ylong_json` 模块提供了 JSON 语法格式文本或字符串的序列化功能,以及对应生成实例的反序列化功能。此外,`ylong_json`模块还适配了第三方库 `serde`。对于实现了 `serde` 库中特定 trait 的结构,可以对其进行序列化与反序列化操作。
|
||||
|
||||
如果需要查看详细的接口说明请查看对应接口的 docs,可以使用 `cargo doc --open` 生成并查看 docs。
|
||||
|
||||
## 功能一:生成 JSON 实例
|
||||
|
||||
(1)可以使用 `JsonValue` 所具有的四种方法从不同的来源生成 `JsonValue` 实例:
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use std::str::FromStr;
|
||||
use std::io::Read;
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
fn create_json_value_instance() {
|
||||
let str: &str = "";
|
||||
// 可以使用 from_str 接口,从 &str 类型尝试生成 JsonValue 实例。
|
||||
// 如果传入的 &str 不符合 JSON 语法,会返回对应的 Error。
|
||||
let json_value = JsonValue::from_str(str);
|
||||
|
||||
let text: String = String::from("");
|
||||
// 可以使用 from_text 接口,从一系列实现 AsRef<[u8]> 的类型生成 JsonValue 实例。
|
||||
// 如果传入的文本内容不符合 JSON 语法,会返回对应的 Error。
|
||||
let json_value = JsonValue::from_text(text);
|
||||
|
||||
let path: &str = "";
|
||||
// 可以使用 from_file 接口,从对应路径的文件读取内容,并尝试生成 JsonValue 实例。
|
||||
// 如果传入的 path 不合法或者文本内容不符合 JSON 语法,会返回对应的 Error。
|
||||
let json_value = JsonValue::from_file(path);
|
||||
|
||||
let mut reader: Box<dyn Read> = Box::new(File::open("").unwrap());
|
||||
// 可以使用 from_reader 接口,从实现了 io::Read 的实例中读取文本,并尝试生成 JsonValue 实例。
|
||||
// 如果读取失败或者从 reader 中读取的内容不符合 JSON 语法,会返回对应的 Error。
|
||||
let json_value = JsonValue::from_reader(&mut reader);
|
||||
}
|
||||
```
|
||||
当 `JsonValue` 实例创建成功后,就可以尝试读取和修改对应的内容了。
|
||||
|
||||
(2)如果 JSON 文本中的类型实现了第三方库 `serde::Deserialize` trait,则可以直接将文本内容反序列化为该类型的实例。
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use serde::Deserialize;
|
||||
use ylong_json::deserializer::{from_reader, from_slice, from_st};
|
||||
fn deserialize_json_to_instance() {
|
||||
#[derive(Deserialize, PartialEq, Debug)]
|
||||
struct Example {
|
||||
int: u32,
|
||||
seq: Vec<String>,
|
||||
tup: (i32, i32, i32),
|
||||
}
|
||||
|
||||
// 可以使用 from_str 接口,从 &str 类型生成实例。
|
||||
// 如果传入的 &str 不符合 JSON 语法,会返回对应的 Error。
|
||||
let tr = r#"{"int":1,"seq":["abcd","efgh"],"tup":[1,2,3]}"#;
|
||||
let example = from_str::<Example>(str).unwrap();
|
||||
|
||||
// 可以使用 from_slice 接口,从 &u8 类型生成实例。
|
||||
// 如果传入的 &u8 不符合 JSON 语法,会返回对应的 Error。
|
||||
let slice = str.as_bytes();
|
||||
let example = from_slice::<Example>(slice).unwrap();
|
||||
|
||||
|
||||
// 可以使用 from_reader 接口,从实现了 io::Write 的位置、文件、io流等生成实例。
|
||||
// 如果传入的文本内容不符合 JSON 语法,会返回对应的 Error。
|
||||
let mut file: File = File::open("./example.txt").unwrap();
|
||||
let example = from_reader::<Example>(file).unwrap();
|
||||
}
|
||||
```
|
||||
|
||||
### 功能二:读取、修改键值对
|
||||
`JsonValue` 实例生成成功后,可以通过各种下标来查找对应的键值对(获取到对应 `JsonValue` 的普通引用)。
|
||||
|
||||
&str 和 String 类型的下标可以用于查找 Object 内的键值对;usize 类型的下标可以用于查找 Array 内的键值对。
|
||||
```rust
|
||||
use std::str::FromStr;
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
// 示例的 JSON 字符串
|
||||
const JSON_TEXT: &str = r#"
|
||||
{
|
||||
"key": "value",
|
||||
"array": [1, 2, 3]
|
||||
}
|
||||
"#;
|
||||
|
||||
fn find_key_value_pair() {
|
||||
// 根据示例字符串创建 JsonValue 实例,语法正确所以此处解析必定成功,使用 unwrap。
|
||||
let json_value = JsonValue::from_str(JSON_TEXT).unwrap();
|
||||
|
||||
// 由于 json 本身也是一个表,所以可以使用 &str 类型获取内部值的普通引用。
|
||||
let value: &JsonValue = &json_value["key"];
|
||||
|
||||
// 可以通过 &str 类型先获取到 “array” 成员的普通引用,再根据 usize 类型获取对应元素的普通引用。
|
||||
let array_item: &JsonValue = &json_value["array"][0];
|
||||
|
||||
// 如果尝试查找一个不存在表中的键,会返回 &JsonValue::Null。
|
||||
let no_such_key: &JsonValue = &json_value["no_such_key"];
|
||||
|
||||
// 对 Array 类型查找时,若下标超过 Array 长度,也会返回 &JsonValue::Null。
|
||||
let no_such_index: &JsonValue = &json_value["array"][100];
|
||||
|
||||
// 对一个 Object 和 Array 类型以外的 JsonValue 类型使用下标访问也会返回 &JsonValue::Null。
|
||||
let invalid_index: &JsonValue = &json_value["key"]["invalid"];
|
||||
let invalid_index: &JsonValue = &json_value["key"][0];
|
||||
}
|
||||
```
|
||||
也可以通过相同方法获取到对应 `JsonValue` 的可变引用,获取到可变引用后可以对其进行修改,修改时需要注意符合 JSON 语法。
|
||||
```rust
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
// 示例的 JSON 字符串
|
||||
const JSON_TEXT: &str = r#"
|
||||
{
|
||||
"key": "value",
|
||||
"array": [1, 2, 3]
|
||||
}
|
||||
"#;
|
||||
|
||||
fn modify_key_value_pair() {
|
||||
// 根据示例字符串创建 JsonValue 实例,语法正确所以此处解析必定成功,使用 unwrap。
|
||||
// 此处由于需要获取可变引用,JSON 实例需要可变。
|
||||
let mut json_value = JsonValue::from_str(JSON_TEXT).unwrap();
|
||||
|
||||
// 通过 “key” 获取到对应成员的可变引用,并将其设置为数值 123。
|
||||
// 库中给许多基本类型实现了从自身到 JsonValue 的转换,所以可以通过 into() 方法转换为 JsonValue。
|
||||
// 执行此句代码后,表中内容如下:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [1, 2, 3]
|
||||
// }
|
||||
json_value["key"] = 123_i32.into();
|
||||
|
||||
// 通过 “array” 和下标 0 获取到对应成员的可变引用,并将其设置为数值 123。
|
||||
// 执行此句代码后,表中内容如下:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [123, 2, 3]
|
||||
// }
|
||||
json_value["array"][0] = 123_i32.into();
|
||||
|
||||
// 如果尝试获取一个不存在表中的键的可变引用,会在表中插入该键且对应值为 JsonValue::Null,并在此基础上进行修改。
|
||||
// 执行此行代码后,json_value 中会增加一个成员 “no_such_key”,且值为数值 123。
|
||||
// 表中内容如下:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [123, 2, 3],
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["no_such_key"] = 123_i32.into();
|
||||
|
||||
// 对 Array 类型的成员尝试获取可变引用时,若下标超过 Array 长度,
|
||||
// 会在 Array 末尾插入一个 JsonValue::Null,并返回该位置的可变引用。
|
||||
// 执行此行代码后,json_value 的 “array” 成员的长度变为 4。
|
||||
// 表中内容如下:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": [123, 2, 3, 123],
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["array"][100] = 123_i32.into();
|
||||
|
||||
// 对一个非 Object 类型使用 &str 类型或 String 下标获取可变引用时,
|
||||
// 会将该值替换为一个空 Object,然后再用此下标对其进行访问。
|
||||
// 执行此代码后,json_value 的 array 成员变成 Object 类型,且含有一个键值对:“key” => 123。
|
||||
// 表中内容如下:
|
||||
// {
|
||||
// "key": 123,
|
||||
// "array": {
|
||||
// "key": 123
|
||||
// },
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["array"]["key"] = 123_i32.into();
|
||||
|
||||
// 对一个非 Array 类型使用 usize 类型下标获取可变引用时,
|
||||
// 会将该值替换成一个空 Array,然后再用此下标对其进行访问。
|
||||
// 执行此代码后,json_value 的 key 成员变成 Array 类型,且含有一个成员: key[0] => 123
|
||||
// 表中内容如下:
|
||||
// {
|
||||
// "key": [123],
|
||||
// "array": {
|
||||
// "key": 123
|
||||
// },
|
||||
// "no_such_key": 123
|
||||
// }
|
||||
json_value["key"][0] = 123_i32.into();
|
||||
}
|
||||
```
|
||||
|
||||
### 功能三:输出 JSON 文本
|
||||
(1)当拥有一个 `JsonValue` 实例时,可以将该 `JsonValue` 实例转化成文本并输出到指定位置:字符串、文件、网络等。
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use ylong_json::JsonValue;
|
||||
|
||||
fn output_json_text(json_value: JsonValue) {
|
||||
// 使用 to_compact_string() 接口将 json_value 输出成一个字符串。
|
||||
let string = json_value.to_compact_string().unwrap();
|
||||
|
||||
// 使用 compact_encode() 接口将 JSON 文本输出到指定实现了 io::Write 的位置,文件、io流等。
|
||||
let mut file: File = File::open("").unwrap();
|
||||
let _ = json_value.compact_encode(&mut file);
|
||||
}
|
||||
```
|
||||
由于 JSON 内部元素没有较强的顺序要求,所以成员的输出顺序会有一定随机性,但是不影响 JSON 文本的语义。
|
||||
|
||||
(2)可以将一个实现了第三方库 `serde::Serialize` trait 的类型实例序列化为 JSON 文本。
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use serde::Serialize;
|
||||
use ylong_json::serializer_compact::{to_string, to_writer};
|
||||
|
||||
fn output_json_text() {
|
||||
#[derive(Serialize)]
|
||||
struct Exmaple {
|
||||
int: u32,
|
||||
seq: Vec<&'static str>,
|
||||
tup: (i32, i32, i32),
|
||||
}
|
||||
|
||||
let example = Example {
|
||||
int: 1,
|
||||
seq: vec!["a", "b"],
|
||||
tup: (1, 2, 3),
|
||||
};
|
||||
|
||||
// 使用 to_string() 接口将 value 输出成一个字符串。
|
||||
let string = to_string(&example).unwrap();
|
||||
|
||||
// 使用 to_writer() 接口将 JSON 文本输出到指定实现了 io::Write 的位置,文件、io流等。
|
||||
let mut file: File = File::open("./example.txt").unwrap();
|
||||
let _ = to_writer(&example, &mut file);
|
||||
}
|
||||
```
|
BIN
figure/ylong_json_inner_structure.png
Normal file
BIN
figure/ylong_json_inner_structure.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
BIN
figure/ylong_json_oh_relate.png
Normal file
BIN
figure/ylong_json_oh_relate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Loading…
Reference in New Issue
Block a user