1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
<h1 align="center">结构化渲染</h1>
<p align="center">
使用 structural_renderer 特性将结果渲染为序列化文本
</p>
启用 `structural_renderer` 后,你的程序可以通过 `--json`、`--yaml` 等参数将输出切换为结构化格式,方便与其他工具集成。
## 开启特性
```toml
[dependencies.mingling]
features = ["structural_renderer"]
```
`structural_renderer` 会自动启用 `json_serde_fmt`。
如果需要更多格式,可以启用 `structural_renderer_full`(包含 JSON、YAML、TOML、RON)。
> [!NOTE]
> 若需要定制输出类型,可以查看 [特性](./pages/other/features)
## 基本用法
启用 `StructuralRendererSetup` 后,用 `pack_structural!` 替代 `pack!` 来声明支持结构化输出的类型:
```rust
// Features: ["structural_renderer"]
// Dependencies:
// serde = "1"
@@@use mingling::setup::StructuralRendererSetup;
@@@dispatcher!("render", CMDRender => EntryRender);
// pack_structural! 等价于 pack! + StructuralData
pack_structural!(ResultInfo = (String, i32));
#[chain]
fn handle_render(args: EntryRender) -> Next {
let name = args.inner.first().cloned().unwrap_or_default();
let age = args.inner.get(1).and_then(|s| s.parse().ok()).unwrap_or(0);
ResultInfo::new((name, age))
}
#[renderer]
fn render_info(r: ResultInfo) {
r_println!("{:?}", *r);
}
```
运行效果:
```text
~# my-cli render Bob 22
("Bob", 22)
~# my-cli render Bob 22 --json
{"inner":["Bob",22]}
```
用户传入 `--json` 时,框架自动将渲染结果序列化为 JSON,无需修改业务代码。
## 自定义输出结构
`pack_structural!` 的默认输出包含 `inner` 字段。要完全控制输出结构,可以用 `#[derive(StructuralData, Serialize, Groupped)]` 手动定义类型:
```rust
// Features: ["structural_renderer"]
// Dependencies:
// serde = "1"
@@@use mingling::prelude::*;
@@@use mingling::setup::StructuralRendererSetup;
@@@use mingling::StructuralData;
@@@use serde::Serialize;
@@@dispatcher!("render", CMDRender => EntryRender);
#[derive(Serialize, StructuralData, Groupped)]
struct Info {
name: String,
age: i32,
}
#[chain]
fn handle_render(args: EntryRender) -> Next {
let name = args.inner.first().cloned().unwrap_or_default();
let age = args.inner.get(1).and_then(|s| s.parse().ok()).unwrap_or(0);
Info { name, age }.to_render()
}
#[renderer]
fn render_info(info: Info) {
r_println!("{} is {} years old", info.name, info.age);
}
@@@
@@@fn main() {
@@@ let mut program = ThisProgram::new();
@@@ program.with_setup(StructuralRendererSetup);
@@@ program.with_dispatcher(CMDRender);
@@@ program.exec();
@@@}
@@@gen_program!();
```
这时 `--json` 输出:
```json
{ "name": "Bob", "age": 22 }
```
## 注意事项
- 支持格式:JSON、YAML、TOML、RON(取决于启用的特性)
- `StructuralRendererSetup` 注册 `--json`、`--yaml`、`--toml`、`--ron` 等全局参数
> [!NOTE]
> 每个类型仍需一个**空的 Renderer**,否则该类型 **不被视为可渲染**
详见 [example-structural-renderer](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-structural-renderer)。
<p align="center" style="font-size: 0.85em; color: gray;">
Written by @Weicao-CatilGrass
</p>
|