我需要更新任意输入文件的特定字段,而无需触及我的程序不知道的任何键或值。
这是一个示例输入文件:
{
"alpha": {
"a": 1,
"z": 2
},
"beta": "b"
}
我想更新alpha.a
100:
{
"alpha": {
"a": 101,
"z": 2
},
"beta": "b"
}
serde_json::Value
可以使用and之类的类型来执行此操作toml::value::Value
,但是此代码非常麻烦:
extern crate serde; // 1.0.66
extern crate serde_json; // 1.0.21
use serde_json::Value;
fn main() {
let input = r#"{
"alpha": {
"a": 1,
"z": 2
},
"beta": "b"
}"#;
let mut to_change: Value = serde_json::from_str(input).unwrap();
{
let obj = to_change.as_object_mut().unwrap();
let alpha = obj.get_mut("alpha").unwrap();
let obj = alpha.as_object_mut().unwrap();
let num = {
let a = obj.get("a").unwrap();
let mut num = a.as_i64().unwrap();
num += 100;
num
};
obj.insert("a".into(), Value::Number(num.into()));
}
println!("{}", serde_json::to_string_pretty(&to_change).unwrap());
}
我宁愿使用干净的派生语法:
extern crate serde; // 1.0.66
#[macro_use]
extern crate serde_derive; // 1.0.66
extern crate serde_json; // 1.0.21
#[derive(Debug, Deserialize, Serialize)]
struct WhatICareAbout {
alpha: Alpha,
}
#[derive(Debug, Deserialize, Serialize)]
struct Alpha {
a: i32,
}
fn main() {
let input = r#"{
"alpha": {
"a": 1,
"z": 2
},
"beta": "b"
}"#;
let mut subobject: WhatICareAbout = serde_json::from_str(input).unwrap();
subobject.alpha.a += 1;
println!("{}", serde_json::to_string_pretty(&subobject).unwrap());
}
这会运行,但会删除任何未知键:
{
"alpha": {
"a": 2
}
}
有没有一种方法可以在使用漂亮Deserialize
和Serialize
实现的同时仍然保留我不知道的键和值?
一个理想的答案是:
- 适用于大多数 Serde 格式——我在这里展示的是 JSON,但我真正的代码是 TOML。
- 允许添加、更新和删除字段。