Reputation: 10581
A simple code:
use serde::Serialize;
#[derive(Serialize)]
struct MyStruct {
foo: Result<u32, String>
}
fn main() {
let m = MyStruct {
foo: Ok(43)
};
let n = MyStruct {
foo: Err("oh no!".into())
};
println!("{}", serde_json::to_string_pretty(&m).unwrap());
println!("{}", serde_json::to_string_pretty(&n).unwrap());
}
This outputs (playground):
{
"foo": {
"Ok": 43
}
}
{
"foo": {
"Err": "oh no!"
}
}
Can I modify the serializer to have a custom output for Result<T,E>
? I would like something like:
// No "Ok" field in case of Ok(T)
{
"foo": 43
}
// Rename "Err" to "error" in case of Err(E)
{
"foo": {
"error": "oh no!"
}
}
Upvotes: 0
Views: 959
Reputation: 58835
Serde attributes are not powerful enough to do the transformation from the default Result
serialization to what you want, so you will need to write custom serialization. Fortunately, it is quite simple:
use serde::{Serialize, Serializer, ser::SerializeMap};
struct MyStruct {
foo: Result<u32, String>
}
impl Serialize for MyStruct {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map = serializer.serialize_map(Some(1))?;
match &self.foo {
Ok(value) => map.serialize_entry("foo", &value)?,
Err(error) => map.serialize_entry("foo", &MyError { error } )?,
}
map.end()
}
}
// This is just used internally to get the nested error field
#[derive(Serialize)]
struct MyError<E> {
error: E,
}
Upvotes: 4