我已经在这上面花了近一个小时,所以这是一个真正的碰壁 case .

由于我无法控制的原因,我正在使用的一个内部服务为我提供了如下形式的JSON

    let dirty_string = r#"\"{\\\"key1\\\":\\\"val1\\\",\\\"key2\\\":\\\"val2\\\"}\""#;

显然,这看起来不太对劲.我的计划是使用serde_json来构造适当的 struct ,但这不起作用.

我已经try 了各种方法来删除多个转义.

我try 过使用各种形式的替换

let to_format = dirty_string.replace("\\\\", r#""#);

给出了这个

"\\\"{\\\"key1\\\":\\\"val1\\\",\\\"key2\\\":\\\"val2\\\"}\\\""基本上让事情变得更糟

let to_format = dirty_string.replace("\\", r#""#); 给出了这个

"\"{\"key1\":\"val1\",\"key2\":\"val2\"}\""

它看起来就在那里,但并不起作用,因为当我试图将其解析到 struct 中时,它失败了

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
struct Parsed {
    key1: String,
    key2: String
}

let to_struct: Parsed = serde_json::from_str(&to_format).unwrap();
dbg!(to_struct);

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error("invalid type: string \"{\", expected struct Parsed", line: 1, column: 3)', src/main.rs:440:62
stack backtrace:
   0: rust_begin_unwind

所以我真的很感谢你们的帮助.

我如何才能成功地删除这个恼人的反斜杠,使其成为有效的json字符串,然后我可以将其解析为 struct .

推荐答案

您得到的是一个JSON字符串,它再次被编码为JSON,并最终将字符反斜杠转义(带有PHPaddslashes()的味道).因此,您需要按顺序执行以下步骤:

  • go 掉一组反斜杠,这将产生一个新的字符串.
  • JSON-从新的字符串中解码另一个字符串.
  • 最后,将JSON反序列化到 struct 中.

例如:

use std::error::Error;

use serde::Deserialize;

#[derive(Deserialize, Debug)]
struct Data {
    pub key1: String,
    pub key2: String,
}

fn stripslashes(s: &str) -> Option<String> {
    let mut n = String::new();

    let mut chars = s.chars();

    while let Some(c) = chars.next() {
        n.push(match c {
            '\\' => chars.next()?,
            c => c,
        });
    }

    Some(n)
}

fn main() -> Result<(), Box<dyn Error>> {
    let dirty_string = r#"\"{\\\"key1\\\":\\\"val1\\\",\\\"key2\\\":\\\"val2\\\"}\""#;

    let s = stripslashes(&dirty_string).expect("stripslashes failed");
    let s: String = serde_json::from_str(&s)?;

    let data: Data = serde_json::from_str(&s)?;

    println!("{:?}", data);

    Ok(())
}

这会产生以下结果:

Data { key1: "val1", key2: "val2" }

Rust相关问答推荐

为什么是!为Rust中的RwLockReadGuard和RwLockWriteGuard实现的发送特征?

是否可以为`T:Copy`执行`T. clone`的测试

通过解引用将值移出Box(以及它被脱糖到什么地方)?

"value is never read警告似乎不正确.我应该忽略它吗?

Rust类似功能是C++命名空间吗?

同时从不同线程调用DLL的不同函数会出现分段错误或产生STATUS_STACK_BUFFER_OVERRUN

当T不执行Copy时,如何返回Arc Mutex T后面的值?

铁 rust 中的泛型:不能将`<;T作为添加>;::Output`除以`{Float}`

`actix-web` 使用提供的 `tokio` 运行时有何用途?

在什么情况下 `..._or()` 比 `..._or_else(|| {})` 更好,为什么?

我们可以在 Rust 切片中使用步骤吗?

根据掩码将 simd 通道设置为 0 的惯用方法?

Rust 为什么被视为borrow ?

trait 对象指针的生命周期

按下 Ctrl + C 时优雅地停止命令并退出进程

没有得到无法返回引用局部变量`queues`的值返回引用当前函数拥有的数据的值的重复逻辑

返回迭代器的特征

在 Rust 中,将可变引用传递给函数的机制是什么?

当用作函数参数时,不强制执行与绑定的关联类型

为什么 Rust 中的关联类型需要明确的生命周期注释?