我正在尝试生成如下所示的 json 对象
// final json output expected
{
"j1": {
"1981": {
"income": 215
},
"1982": {
"income": 350
},
},
"j2": {
"1981": {
"income": 100
},
"1982": {
"income": 215
},
}
}
我有以下代码
use serde_json::{Value, Map};
struct s {
name: String,
year: i32,
income: i64
}
fn main() {
let rows :Vec<s> = vec!(
s { name: "j1".to_string(), year: 1981, income: 100},
s { name: "j1".to_string(), year: 1981, income: 115},
s { name: "j1".to_string(), year: 1982, income: 120},
s { name: "j1".to_string(), year: 1982, income: 100},
s { name: "j1".to_string(), year: 1982, income: 130},
s { name: "j2".to_string(), year: 1981, income: 100},
s { name: "j2".to_string(), year: 1982, income: 120},
s { name: "j2".to_string(), year: 1982, income: 130}
);
let mut data_map: Map<String, Value> = Map::new();
for row in rows {
let mut name: &Map<String, Value> = match data_map.get(&row.name) {
Some(val) => { &val.as_object().unwrap() },
None => { &Map::new() }
};
let mut year: &Map<String, Value> = match data_map.get(&row.year.to_string()) {
Some(val) => { &val.as_object().unwrap() },
None => { &Map::new() }
};
let income: i64 = year.get("income").unwrap_or(&Value::Number(0i64.into())).as_i64().unwrap() + row.income;
year.insert("income".to_string(), Value::Number(income.into()));
}
}
我创建了这个代码来提问。我还咨询了 deepseek 等
我收到的错误消息是
error[E0596]: cannot borrow `*year` as mutable, as it is behind a `&` reference
--> src\main.rs:32:9
|
32 | year.insert("income".to_string(), Value::Number(income.into()));
| ^^^^ `year` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
help: consider changing this binding's type
|
27 | let mut year: &mut serde_json::Map<std::string::String, Value> = match data_map.get(&row.year.to_string()) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
显然我对引用和借用理解不足。如能得到任何帮助我将不胜感激。
首先,您通常不会手动创建 JSON。您可以创建它的 Rust 表示,然后将
serde_json
其转换为 JSON。这意味着,不要Value
自己处理。当然,您也可以手动构建 JSON,但这并没有什么优势
serde_json
。这是一个解决方案。首先,我们需要以下依赖项
Cargo.toml
:代码如下:
关于您原始代码中的借用错误:我不确定该如何帮助您。其中有很多错误,既有所有权问题,也有逻辑问题。
我假设
data_map
您打算使用键来查询成员row.name
,如果不存在,则插入新映射。我看到您创建了一个新映射,但从未将其插入data_map
任何地方。其余问题都是一堆&
错误,有时是因为值已经是引用,有时是因为它们指向临时变量并且您创建了悬空引用。我很想更详细地剖析你的代码并向你解释错误,但这样做有点太令人困惑了:D
相反,下面是重写的内容。也许它有助于你的理解:
但同样,除非绝对必要,否则不要这样做;
serde_json
实际上不应该这样使用。Value
直接使用只会导致大量as_<type>().unwrap()
强制转换,并且与使用实现的 Rust 类型相比,没有真正的优势serde::Serialize
。这就是它serde_json
的使用方式;请参见#[derive(Serialize)]
我的第一个示例。我建议阅读serde.rs以获取更多信息。你想要实现的目标不明确:
在您的第一个代码片段(预期的 JSON 输出)中,您似乎想要一个 JSON 对象,其中包含嵌套对象列表,其中每个对象都有一个名称,例如
j1
对应于每年收入的对象列表。但这并不是编写 JSON 的标准方式。通常,变量名称和值由列分隔
:
,并且同一类型的多个元素存储在数组中,这就是您在第二个代码片段中所做的。我不明白你为什么在这里尝试使用 serde_json::Map。如果你只想将对象打印为 json 字符串
rows
,则可以将代码修改为以下内容(确保通过运行添加具有派生功能的 serde 包cargo add serde --features=derive
)您应该看到以下内容(格式化为多行之后):
希望这有帮助