如何在Rust中取消转义已经多次转义的字符串?

huangapple go评论87阅读模式
英文:

How do I unescaped, string that has been escaped multiple times in Rust?

问题

我已经花了将近一个小时在这个问题上,所以这确实是一个碰壁的情况。

由于我无法控制的原因,我正在使用的内部服务给我传递了一个 JSON 数据,它的形式如下:

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

显然,这看起来不正确。我的计划是将其取出并使用 serde_json 构建适当的结构,但这并不起作用。

我尝试了各种方法来去掉多个转义符。

我尝试了各种形式的替换,比如:

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

会得到这个结果:

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

基本上使问题更加复杂。

这个:

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

会得到这个结果:

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

看起来接近了,但不起作用,因为当我尝试将其解析成结构时,它会失败。

#[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);

线程 'main' 在 'Result::unwrap()' 上发生了恐慌,值为 'Err':Error("invalid type: string "{",expected struct Parsed", line: 1, column: 3),src/main.rs:440:62

所以我真的很感激在这里得到帮助。

我应该如何成功去掉这些恼人的反斜杠,使其成为一个有效的 JSON 字符串,然后可以解析到结构中呢?

英文:

I have spent close to an hour on this already, so this is a true case of hitting a wall.

For reasons beyond my control, an internal service I am using hands me a JSON that is in this form

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

Now obviously this does not look right. My plan it to take this and use serde_json to construct the appropriate struct but that does not work.

I have tried various ways to remove the multiple escapes.

I have tried various form of using replace

This

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

gives this

"\\\"{\\\"key1\\\":\\\"val1\\\",\\\"key2\\\":\\\"val2\\\"}\\\"" basically making the matter worse

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

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

which looks like almost there, but does not work because when I try to parse it into the struct it fails

#[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

So I will really appreciate help here.

How exactly can I successfully removing this annoying back slashes such that it becomes a valid json string that I can then parse to the struct.

答案1

得分: 2

你可以添加引号并将其通过三次 serde_json 迭代处理:

let dirty_string = r#""{\"key1\":\"val1\",\"key2\":\"val2\"}""#;
let s: String = serde_json::from_str(&format!(r#""{}""#, dirty_string)).unwrap();
let s: String = serde_json::from_str(&s).unwrap();
let value: serde_json::Value = serde_json::from_str(&s).unwrap();
println!("{value:#?}");
英文:

You can add quotes and put it through three iterations of serde_json:

let dirty_string = r#"\"{\\\"key1\\\":\\\"val1\\\",\\\"key2\\\":\\\"val2\\\"}\""#;
let s: String = serde_json::from_str(&format!(r#""{}""#, dirty_string)).unwrap();
let s: String = serde_json::from_str(&s).unwrap();
let value: serde_json::Value = serde_json::from_str(&s).unwrap();
println!("{value:#?}");

答案2

得分: 1

以下是翻译好的部分:

你现在有的是一个JSON字符串,它再次被编码为JSON,并最终进行了字符反斜杠转义(类似于PHP的addslashes())。因此,你需要按照以下步骤进行操作:

  • 去除一组反斜杠,将产生一个新字符串。
  • 从新字符串中进行JSON解码。
  • 最后,将其反序列化为结构体。

例如:

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" }
英文:

What you have is a JSON string that was again encoded as JSON, and finally had characters backslash-escaped (smells of PHP's addslashes()). So you need to do these steps in order:

  • Strip one set of backslashes, which will produce a new string.
  • JSON-decode another String from the new one.
  • Finally, JSON-deserialize into the struct.

For example:

use std::error::Error;

use serde::Deserialize;

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

fn stripslashes(s: &amp;str) -&gt; Option&lt;String&gt; {
    let mut n = String::new();

    let mut chars = s.chars();

    while let Some(c) = chars.next() {
        n.push(match c {
            &#39;\\&#39; =&gt; chars.next()?,
            c =&gt; c,
        });
    }

    Some(n)
}

fn main() -&gt; Result&lt;(), Box&lt;dyn Error&gt;&gt; {
    let dirty_string = r#&quot;\&quot;{\\\&quot;key1\\\&quot;:\\\&quot;val1\\\&quot;,\\\&quot;key2\\\&quot;:\\\&quot;val2\\\&quot;}\&quot;&quot;#;

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

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

    println!(&quot;{:?}&quot;, data);

    Ok(())
}

This outputs:

Data { key1: &quot;val1&quot;, key2: &quot;val2&quot; }

huangapple
  • 本文由 发表于 2023年5月30日 11:01:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76361360.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定