Мне нужно обновить определенные поля произвольного входного файла, не касаясь клавиш или значений, о которых моя программа не знает.
Вот пример входного файла:
{
"alpha": {
"a": 1,
"z": 2
},
"beta": "b"
}
Я бы хотел обновить alpha.a
на 100:
{
"alpha": {
"a": 101,
"z": 2
},
"beta": "b"
}
Это можно сделать с помощью таких типов, как serde_json::Value
и 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.
- Разрешить добавление, обновление и удаление полей.