为什么Go和Rust序列化结果不一致?

-2 marshalling go rust serde-json

我想要的结果如下\xef\xbc\x8c,但Rust的结果是另一个。

\n
 [123 34 66 111 100 121 34 58 34 97 71 86 115 98 71 56 61 34 125]\n
Run Code Online (Sandbox Code Playgroud)\n

戈兰样本:

\n
type Response struct {\n    Body    []byte\n}\nfunc Test_Marshal(t *testing.T)  {\n    body := "hello"\n    resp := &Response{\n        Body:[]byte(body),\n    }\n    t.Log("resp:", resp)\n    result, _ := json.Marshal(resp)\n    t.Log("result: ", result)\n}\n
Run Code Online (Sandbox Code Playgroud)\n

去结果:

\n
    aa_test.go:17: resp: &{[104 101 108 108 111]}\n    aa_test.go:19: result:  [123 34 66 111 100 121 34 58 34 97 71 86 115 98 71 56 61 34 125]\n
Run Code Online (Sandbox Code Playgroud)\n

铁锈样品:

\n
use serde_json::{Result, Value};\nuse serde::Serialize;\n\n#[derive(Serialize, Debug)]\npub struct Response {\n    pub body: ::std::vec::Vec<u8>,\n}\n\nfn main() {\n    let body_str = "hello".to_string();\n    let resp = Response {\n        body: Vec::from(body_str)\n    };\n\n    println!("resp: {:?}", resp);\n\n    let result = serde_json::to_vec(&resp).unwrap();\n    println!("result: {:?}",result)\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n

生锈结果

\n
resp: Response { body: [104, 101, 108, 108, 111] }\nresult: [123, 34, 98, 111, 100, 121, 34, 58, 91, 49, 48, 52, 44, 49, 48, 49, 44, 49, 48, 56, 44, 49, 48, 56, 44, 49, 49, 49, 93, 125]\n\n
Run Code Online (Sandbox Code Playgroud)\n

Cer*_*rus 5

如果我们将您的输出从字节数组转换为 ASCII 字符串(我使用了简单的 Javascript 代码 - array.map(ch => String.fromCharCode(ch)).join("")),我们将得到以下结果:

// for Rust
{"body":[104,101,108,108,111]}
// for Go
{"Body":"aGVsbG8="}
Run Code Online (Sandbox Code Playgroud)

所以,似乎有两个区别:

  • 第一个也是最明显的是字段命名。两个序列化程序都将 JSON 中的字段名称保留为源代码中的字段名称,因此在 Go 中是Body(大写),而在 Rust 中是body(小写)。
  • 第二个是 Rust 按原样对值进行编码 - 即字节数组被视为数字向量(它没有得到任何特殊处理)。然而,在 Go 中,它被转换为 Base64 字符串 - 这是一个明确记录的异常,可能是因为在大多数情况下这是预期的行为。

现在,在这里做什么?这取决于您想要使用什么行为。我不知道如何用 Go 改变输出,所以我认为它是正确的,而 Rust 需要调整。

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
pub struct Response {
    #[serde(with="base64")]
    pub body: Vec<u8>,
}

mod base64 {
    use serde::{Serialize, Deserialize};
    use serde::{Deserializer, Serializer};

    pub fn serialize<S: Serializer>(v: &Vec<u8>, s: S) -> Result<S::Ok, S::Error> {
        let base64 = base64::encode(v);
        String::serialize(&base64, s)
    }
    
    pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
        let base64 = String::deserialize(d)?;
        base64::decode(base64.as_bytes())
            .map_err(|e| serde::de::Error::custom(e))
    }
}
Run Code Online (Sandbox Code Playgroud)