Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add value of a method to serde serialization output

Tags:

rust

Is there a way to add the value of a method to the serialization output of serde when the struct derives Serialize? I'm looking for something like a "virtual field".

I know I can define my own Serializer / Visitor or use serde_json::builder to get a Value, I just wanted to check first if there was any way to do this using serde_macro magic.

To be clear I want something like this:

#[derive(Serialize, Deserialize, Debug)]
struct Foo {
    bar: String,
    #[serde(call="Foo::baz")]
    baz: i32 // but this is not a real field
}

impl Foo {
    fn baz(&self) -> i32 { self.bar.len() as i32 }
}
like image 377
Jacob Brown Avatar asked Mar 22 '16 15:03

Jacob Brown


People also ask

How do I implement serialize in serde?

Implementing Serialize. The Serialize trait looks like this: This method's job is to take your type (&self) and map it into the Serde data model by invoking exactly one of the methods on the given Serializer. In most cases Serde's derive is able to generate an appropriate implementation of Serialize for structs and enums defined in your crate.

How do you serialize a type in a serializer?

Implementing Serialize The Serialize trait looks like this: pub trait Serialize { fn serialize<S> (&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer; } This method's job is to take your type (&self) and map it into the Serde data model by invoking exactly one of the methods on the given Serializer.

What types of Rust programs can be serialized using serde?

Serde provides Serialize implementations for many Rust primitive and standard library types. The complete list is here. All of these can be serialized using Serde out of the box. Additionally, Serde provides a procedural macro called serde_derive to automatically generate Serialize implementations for structs and enums in your program.

What is the use of derive method in serde?

This method's job is to take your type (&self) and map it into the Serde data modelby invoking exactly one of the methods on the given Serializer. In most cases Serde's deriveis able to generate an appropriate implementation of Serializefor structs and enums defined in your crate.


1 Answers

Here is what I am using now. It's still verbose, and I don't know if it is the best way to handle this, but I thought I would add it here for the record:

#[derive(Deserialize, Debug)]
struct Foo {
    bar: String
}

impl Foo {
    fn baz(&self) -> i32 { self.bar.len() as i32 }
}

impl ::serde::Serialize for Foo {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> 
        where S: ::serde::Serializer {

        #[derive(Serialize)]
        struct Extended<'a> {
            bar: &'a String,
            baz: i32
        }

        let ext = Extended {
            bar: &self.bar,
            baz: self.baz()
        };

        Ok(try!(ext.serialize(serializer)))
    }
}
like image 102
Jacob Brown Avatar answered Oct 21 '22 20:10

Jacob Brown