6 个版本
0.9.5 | 2024年7月19日 |
---|---|
0.9.4 | 2024年7月19日 |
#280 in 编码
每月499次下载
27KB
430 行
json-template
json-template
是一个允许您创建 JSON 模板的库。
{
"personal_info": "{file:additional.json}",
"info": "{personal_info.name} {personal_info.last_name} is {personal_info.age} years old"
}
{
"name": "Danilo",
"last_name": "Guanabara",
"age": 36
}
可以被渲染为
{
"personal_info": {
"age": 36,
"name": "Danilo",
"last_name": "Guanabara"
},
"info": "Danilo Guanabara is 36 years old"
}
功能
链式解析器
{
"my": "Danilo",
"name": "{my}",
"is": "{name}
}
每个路径段都是一个占位符
{
"data": "{{file:data.json}.property}
}
函数
内置函数
函数 | 描述 |
---|---|
{file:path} |
从相对路径加载一个文件。如果您反序列化一个文件,它的基本目录会自动设置。您也可以使用 Context::set_directory 手动设置。 |
{string:path} |
将 serde_json::Value 转换为 serde_json::Value::String 。如果您需要将数字反序列化为字符串,这很有用。 |
{compose:{a}, {b}, ...} |
将 N 个对象组合在一起。如果属性不存在,则会添加。如果属性是数组,则两个数组将被连接。输入是占位符。 |
查看 自定义函数
代码示例以了解如何创建自定义函数。
代码示例
您始终可以检查 测试 :)
从内存中
use json_template::*;
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Data {
name: String,
age: usize,
age_str: String,
info: String,
time: String
}
let json = r#"{
"data": {
"name": "Danilo",
"age": 36
},
"name": "{data.name}",
"age": "{data.age}",
"age_str": "{string:data.age}",
"info": "{data.name} is {data.age} years old.",
"time": "{data.time}"
}"#;
let context = Context::new()
.with_data(serde_json::json!({
"data": {
"time": "now"
}
}));
let data: Data = Deserializer::new().deserialize_with_context(json, &context).unwrap();
assert_eq!(data, Data {
name: "Danilo".into(),
age: 36,
age_str: "36".into(),
info: "Danilo is 36 years old.".into(),
time: "now".into()
})
请注意,age_str
字段是一个字符串,而 age
字段是一个数字。
简单的 "{age}"
占位符被替换为 JSON 对象中的相应值。
"{string:age}"
占位符被替换为 JSON 对象中的相应值作为字符串。
格式化占位符,如 "{data.name} is {data.age} years old."
被替换为 JSON 对象中的相应值作为字符串。
尽管 "{string:data.name} is {string:data.age} years old."
也可以工作,但这不是必需的。
从文件中
use json_template::*;
use serde::{Serialize, Deserialize};
use std::path::PathBuf;
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Data {
name: String,
age: usize,
age_str: String,
info: String,
time: String
}
let json = r#"{
"data": "{file:tests/data.json}",
"name": "{data.name}",
"age": "{data.age}",
"age_str": "{string:data.age}",
"info": "{data.name} is {data.age} years old.",
"time": "{data.time}"
}"#;
let directory = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let context = Context::new()
.with_data(serde_json::json!({
"data": {
"time": "now"
}
}))
.with_directory(Some(directory));
let data: Data = Deserializer::new().deserialize_with_context(json, &context).unwrap();
assert_eq!(data, Data {
name: "Danilo".into(),
age: 36,
age_str: "36".into(),
info: "Danilo is 36 years old.".into(),
time: "now".into()
})
或简单地
use json_template::*;
use serde::{Serialize, Deserialize};
use std::path::PathBuf;
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Data {
name: String,
age: usize,
age_str: String,
info: String,
time: String
}
let file = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests")
.join("data-from-file.json");
let context = Context::new()
.with_data(serde_json::json!({
"data": {
"time": "now"
}
}));
let data: Data = Deserializer::new().deserialize_with_context(file, &context).unwrap();
assert_eq!(data, Data {
name: "Danilo".into(),
age: 36,
age_str: "36".into(),
info: "Danilo is 36 years old.".into(),
time: "now".into()
})
自定义函数
use json_template::*;
use serde::{Serialize, Deserialize};
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Time {
duration: std::time::Duration
}
let value = serde_json::json!({ "duration": "{time:5}" });
let context = Context::new().with_function("time", |_deserializer, _context, placeholder| {
let seconds = placeholder
.path()
.str()
.parse::<u64>()
.map_err(|e| serde::de::Error::custom(e))?;
let duration = std::time::Duration::from_secs(seconds);
serde_json::to_value(&duration)
});
let data: Time = Deserializer::new().deserialize_with_context(value, &context).expect("Failed to deserialize");
assert_eq!(data.duration, std::time::Duration::from_secs(5));
依赖
~0.7–1.6MB
~35K SLoC