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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#![doc = r##"Serde wrapper to load/save serializable data from relative paths."##]
#![doc = r##"
This crate provides special wrappers to ser/deserialize type from a file path.
The following wrappers are provided:
"##]
#![cfg_attr(feature = "json", doc = "- [JsonPath]")]
#![cfg_attr(feature = "json", doc = "- [JsonPrettyPath]")]
#![cfg_attr(feature = "json5", doc = "- [Json5Path]")]
#![cfg_attr(feature = "protobuf", doc = "- [ProtobufPath]")]
#![doc = ""]
#![cfg_attr(
feature = "json",
doc = r##"
It enables to read or write the file path instead of data during de/serialization.
For example, we can have a `main.json` file that loads `external.json`.
`main.json`
```json
{
"external": "external.json"
}
```
The type type definition is defined as follows.
```no_run
# fn main() -> anyhow::Result<()> {
use serde_loader::JsonPath;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct Main {
pub external: JsonPath<External>
}
#[derive(Serialize, Deserialize)]
struct External {
data: String
}
// open file
let main: JsonPath<Main> = JsonPath::open("main.json")?;
// access data
let data = &main.external.data;
# Ok(())
# }
```
# Recursive File Loading
The file path is relative to the file where the field is defined.
It tracks file paths automatically and allows recursive file loading.
Suppose we have the following files.
`main.json`
```json
{
"sub": "sub/sub.json"
}
```
`sub/sub.json`
```json
{
"sub": "sub/sub.json"
}
```
`sub/sub/sub_of_sub.json`
```json
{
"sub": "sub/sub_of_sub.json"
}
```
Let's load the files recursively.
```rust
# fn main() -> anyhow::Result<()> {
use serde_loader::JsonPath;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct Main {
pub sub: JsonPath<Sub>
}
#[derive(Serialize, Deserialize)]
struct Sub {
pub sub: JsonPath<SubOfSub>
}
#[derive(Serialize, Deserialize)]
struct SubOfSub {
pub name: String,
pub value: String,
}
let config: JsonPath<Main> = JsonPath::open("tests/config-example/main.json")?;
config.save()?;
# Ok(())
# }
```
"##
)]
mod common;
mod dir_stack;
pub mod error;
pub use abs_path_buf::AbsPathBuf;
pub mod abs_path_buf;
pub use file::FilePath;
pub mod file;
#[cfg(feature = "protobuf")]
pub use protobuf::ProtobufPath;
#[cfg(feature = "protobuf")]
mod protobuf;
#[cfg(feature = "json")]
pub use json::{JsonPath, JsonPrettyPath};
#[cfg(feature = "json")]
pub mod json;
#[cfg(feature = "json5")]
pub use self::json5::Json5Path;
#[cfg(feature = "json5")]
pub mod json5;