Search code examples
jsonrustserdeserde-json

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? The result would be a json

{"foo": [{"a": "something"}, {"a": "something2"}], "b": "something"}

Solution

  • You can get this serialized structure by storing both Foo and Bar2 in another struct and merge them together with #[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. You'd have to do your proposed method by serializing into Values and merging them yourself.