如何修改使用 serde 序列化的 Result<T,E> 的 JSON 输出?
How do I modify the JSON output for a Result<T,E> serialized with serde?
一个简单的代码:
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());
}
这输出 (playground):
{
"foo": {
"Ok": 43
}
}
{
"foo": {
"Err": "oh no!"
}
}
我可以修改序列化程序以具有 Result<T,E>
的自定义输出吗?我想要这样的东西:
// No "Ok" field in case of Ok(T)
{
"foo": 43
}
// Rename "Err" to "error" in case of Err(E)
{
"foo": {
"error": "oh no!"
}
}
Serde attributes 不够强大,无法将默认 Result
序列化转换为您想要的序列化,因此您需要编写自定义序列化。幸运的是,这很简单:
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,
}
一个简单的代码:
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());
}
这输出 (playground):
{
"foo": {
"Ok": 43
}
}
{
"foo": {
"Err": "oh no!"
}
}
我可以修改序列化程序以具有 Result<T,E>
的自定义输出吗?我想要这样的东西:
// No "Ok" field in case of Ok(T)
{
"foo": 43
}
// Rename "Err" to "error" in case of Err(E)
{
"foo": {
"error": "oh no!"
}
}
Serde attributes 不够强大,无法将默认 Result
序列化转换为您想要的序列化,因此您需要编写自定义序列化。幸运的是,这很简单:
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,
}