[英]rust: adding a field to an existing struct with serde_json
I have a pre-defined struct我有一个预定义的结构
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Foo<T>
where T: Serialize
{
foo: T
}
struct Bar{
a: String
}
struct Bar2{
b: String
}
fn main() -> Result<()>
{
let a1 = Bar {a: "something".to_owned(),};
let a2 = Bar {a: "something2".to_owned(),};
let a_vec: Vec<Bar> = vec![a1, a2];
let b = Bar2 {b: "something"}
let b_vec: Vec<Bar2> = vec![b];
//let foo = Foo {foo: vec![a_vec,b_vec]}
}
How can I put both struct under Foo
or is it possible to first serialize Bar
to json and add Bar2
as string literals?如何将两个结构都放在
Foo
下,或者是否可以先将Bar
序列化为 json 并将Bar2
添加为字符串文字? The result would be a json结果将是一个json
{"foo": [{"a": "something"}, {"a": "something2"}], "b": "something"}
You can get this serialized structure by storing both Foo
and Bar2
in another struct and merge them together with #[serde(flatten)]
.您可以通过将
Foo
和Bar2
存储在另一个结构中并将它们与#[serde(flatten)]
合并在一起来获得此序列化结构。 ( playground ): ( 操场):
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Foo<T>
where
T: Serialize,
{
foo: T,
}
#[derive(Debug, Serialize)]
struct Bar {
a: String,
}
#[derive(Debug, Serialize)]
struct Bar2 {
b: String,
}
#[derive(Debug, Serialize)]
struct Outer<T: Serialize> {
#[serde(flatten)]
field_1: Foo<T>,
#[serde(flatten)]
field_2: Bar2,
}
fn main() {
let a1 = Bar {
a: "something".to_owned(),
};
let a2 = Bar {
a: "something2".to_owned(),
};
let a_vec: Vec<Bar> = vec![a1, a2];
let b = Bar2 {
b: "something".to_owned(),
};
let o = Outer {
field_1: Foo { foo: a_vec },
field_2: b,
};
println!("{}", serde_json::to_string(&o).unwrap());
}
{"foo":[{"a":"something"},{"a":"something2"}],"b":"something"}
If instead by "no modification of struct" you meant by only serializing Foo
and just modifying T
, then no its not possible to get that output with serde
directly.如果改为“不修改结构” ,您的意思是仅序列化
Foo
并仅修改T
,那么不可能直接使用serde
获得该输出。 You'd have to do your proposed method by serializing into Value
s and merging them yourself.您必须通过序列化为
Value
并自己合并它们来执行您提出的方法。
I see two problems with your code:我发现您的代码有两个问题:
Serialize
for Bar
and Bar2
.Bar
和Bar2
派生Serialize
。a_vec
and b_vec
into a vector, which you can't do because they're of different type.a_vec
和b_vec
放入一个向量中,但您不能这样做,因为它们的类型不同。 The latter problem can be solved by dynamic dispatch.后一个问题可以通过动态调度来解决。 Instead of putting
a_vec
into the Vec
, you put &a_vec as &dyn Serialize
, ie just give it a reference to some serializable object.不是将
a_vec
放入Vec
,而是将&a_vec as &dyn Serialize
,即只给它一个对某些可序列化对象的引用。 Slight trouble is that this won't work with serde::Serialize
because it's not object safe.小麻烦是这不适用于
serde::Serialize
因为它不是对象安全的。 This is what erased_serde
is for:这就是
erased_serde
的用途:
let foo = Foo::<Vec<&dyn erased_serde::Serialize>> {
foo: vec![&a_vec, &b_vec],
};
println!("{}", serde_json::to_string_pretty(&foo).unwrap());
will work fine.会正常工作。 But it will output
但它会输出
{"foo":[[{"a":"something"},{"a":"something2"}],[{"b":"something"}]]}
which is not what you wanted?这不是你想要的?
To get the output you wanted, ie serialize Foo and add a field to it, you could use #[serde(flatten)]
:要获得您想要的输出,即序列化 Foo 并向其添加一个字段,您可以使用
#[serde(flatten)]
:
let foo = Foo { foo: a_vec };
#[derive(Serialize)]
struct Merge<T1: Serialize, T2: Serialize> {
#[serde(flatten)]
f1: T1,
#[serde(flatten)]
f2: T2,
}
let out = Merge { f1: &foo, f2: &b };
println!("{}", serde_json::to_string_pretty(&out).unwrap());
The output of serializing Merge
both the fields from T1
and T2
.序列化的输出
Merge
来自T1
和T2
的两个字段。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.