为什么我在尝试使用 serde_json 解析数据时总是收到“尾随字符”错误?

Tom*_*rc1 5 json rust

我有一个以 JSON 格式返回请求的服务器。当尝试解析数据时,我总是收到“尾随字符”错误。仅当从邮递员获取 JSON 时才会发生这种情况

let type_of_request = parsed_request[1];
let content_of_msg: Vec<&str> = msg_from_client.split("\r\n\r\n").collect();

println!("{}", content_of_msg[1]); 
// Will print "{"username":"user","password":"password","email":"dwadwad"}"

let res: serde_json::Value = serde_json::from_str(content_of_msg[1]).unwrap();

println!("The username is: {}", res["username"]);
Run Code Online (Sandbox Code Playgroud)

从邮递员获取数据时会发生这种情况:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error("trailing characters", line: 1, column: 60)', src\libcore\result.rs:997:5
Run Code Online (Sandbox Code Playgroud)

但是当 Rust 中有字符串时:

let j = "{\"username\":\"user\",\"password\":\"password\",\"email\":\"dwadwad\"}";

let res: serde_json::Value = serde_json::from_str(j).unwrap();

println!("The username is: {}", res["username"]);
Run Code Online (Sandbox Code Playgroud)

它就像一个魅力:

The username is: "user"
Run Code Online (Sandbox Code Playgroud)

编辑:显然,当我将消息读入缓冲区并将其转换为字符串时,它保存了缓冲区具有的所有 NULL 字符,这些字符当然是尾随字符。

chu*_*ash 4

查看 serde json代码,可以在相关 ErrorCode 枚举元素上方找到以下注释:

/// JSON has non-whitespace trailing characters after the value.
TrailingCharacters,
Run Code Online (Sandbox Code Playgroud)

因此,正如错误代码所暗示的那样,您有一些不是空格的尾随字符。在你的片段中,你说:

println!("{}", content_of_msg[1]); 
// Will print "{"username":"user","password":"password","email":"dwadwad"}"
Run Code Online (Sandbox Code Playgroud)

如果您将打印输出逐字复制并粘贴到此处,我会注意到,我不希望输出包含在前导引号和尾随引号中。这些是您自己添加的还是印刷内容的一部分?如果它们被打印出来,我怀疑这就是你问题的根源。

编辑:

事实上,我几乎可以使用 Rust 中带有前导/尾随引号的原始字符串来重新创建它:

extern crate serde_json;

#[cfg(test)]
mod tests {
    #[test]
    fn test_serde() {
        let s =
            r#""{"username":"user","password":"password","email":"dwadwad"}""#;
        println!("{}", s);
        let _res: serde_json::Value = serde_json::from_str(s).unwrap();
    }
}
Run Code Online (Sandbox Code Playgroud)

通过收益运行它cargo test

test tests::test_serde ... FAILED

failures:

---- tests::test_serde stdout ----
"{"username":"user","password":"password","email":"dwadwad"}"
thread 'tests::test_serde' panicked at 'called `Result::unwrap()` on an `Err` value: Error("trailing characters", line: 1, column: 4)', src/libcore/result.rs:997:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.


failures:
    tests::test_serde
Run Code Online (Sandbox Code Playgroud)

请注意,我的打印输出还包括前导/尾随引号,并且我也收到错误TrailingCharacter,尽管是在不同的列中。

编辑2:

根据您自己添加的包装引号的评论,您已经获得了一个已知的好字符串(您在 Rust 中定义的字符串),以及您认为应该匹配但不匹配的字符串(来自 Postman 的字符串) )。

这是一个数据问题,所以我们应该检查数据。您可以调整以下代码来检查正确的字符串与其他字符串:

#[test]
fn test_str_comp() {
    // known good string we'll compare against                                                                                                                                             
    let good =
        r#"{"username":"user","password":"password","email":"dwadwad"}"#;
    // lengthened string, additional characters                                                                                                                                            
    // also n and a in username are transposed                                                                                                                                             
    let bad =
        r#"{"useranme":"user","password":"password","email":"dwadwad"}abc"#;
    let good_size = good.chars().count();
    let bad_size = bad.chars().count();
    for (idx, (c1, c2)) in (0..)
        .zip(good.chars().zip(bad.chars()))
        .filter(|(_, (c1, c2))| c1 != c2)
    {
        println!(
            "Strings differ at index {}: (good: `{}`, bad: `{}`)",
            idx, c1, c2
        );
    }
    if good_size < bad_size {
        let trailing = bad.chars().skip(good_size);
        println!(
            "bad string contains extra characters: `{}`",
            trailing.collect::<String>()
        );
    } else if good_size > bad_size {
        let trailing = good.chars().skip(bad_size);
        println!(
            "good string contains extra characters: `{}`",
            trailing.collect::<String>()
        );
    }

    assert!(false);
}
Run Code Online (Sandbox Code Playgroud)

对于我的示例,这会导致失败:

test tests::test_str_comp ... FAILED

failures:

---- tests::test_str_comp stdout ----
Strings differ at index 6: (good: `n`, bad: `a`)
Strings differ at index 7: (good: `a`, bad: `n`)
bad string contains extra characters: `abc`
thread 'tests::test_str_comp' panicked at 'assertion failed: false', src/lib.rs:52:9
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.


failures:
    tests::test_str_comp
Run Code Online (Sandbox Code Playgroud)

  • 太感谢了!这帮助我意识到在实际数据之后有很多 NULL,因为我将数据从套接字读入缓冲区。“尾随章程”只是无效的。当消息长度达到 239 时我意识到了这一点。 (2认同)