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

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

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

问题

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

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

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

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

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

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

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

会得到这个结果:

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

基本上使问题更加复杂。

这个:

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

会得到这个结果:

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

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

  1. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
  2. struct Parsed {
  3. key1: String,
  4. key2: String
  5. }
  6. let to_struct: Parsed = serde_json::from_str(&to_format).unwrap();
  7. 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

  1. 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

  1. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
  2. struct Parsed {
  3. key1: String,
  4. key2: String
  5. }
  6. let to_struct: Parsed = serde_json::from_str(&to_format).unwrap();
  7. dbg!(to_struct);
  8. 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
  9. stack backtrace:
  10. 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 迭代处理:

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

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

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

答案2

得分: 1

以下是翻译好的部分:

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

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

例如:

  1. use std::error::Error;
  2. use serde::Deserialize;
  3. #[derive(Deserialize, Debug)]
  4. struct Data {
  5. pub key1: String,
  6. pub key2: String,
  7. }
  8. fn stripslashes(s: &str) -> Option<String> {
  9. let mut n = String::new();
  10. let mut chars = s.chars();
  11. while let Some(c) = chars.next() {
  12. n.push(match c {
  13. '\\' => chars.next()?,
  14. c => c,
  15. });
  16. }
  17. Some(n)
  18. }
  19. fn main() -> Result<(), Box<dyn Error>> {
  20. let dirty_string = r#""{\\"key1\\":\\"val1\\",\\"key2\\":\\"val2\\"}""#;
  21. let s = stripslashes(&dirty_string).expect("stripslashes failed");
  22. let s: String = serde_json::from_str(&s)?;
  23. let data: Data = serde_json::from_str(&s)?;
  24. println!("{:?}", data);
  25. Ok(())
  26. }

这将输出:

  1. 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:

  1. use std::error::Error;
  2. use serde::Deserialize;
  3. #[derive(Deserialize, Debug)]
  4. struct Data {
  5. pub key1: String,
  6. pub key2: String,
  7. }
  8. fn stripslashes(s: &amp;str) -&gt; Option&lt;String&gt; {
  9. let mut n = String::new();
  10. let mut chars = s.chars();
  11. while let Some(c) = chars.next() {
  12. n.push(match c {
  13. &#39;\\&#39; =&gt; chars.next()?,
  14. c =&gt; c,
  15. });
  16. }
  17. Some(n)
  18. }
  19. fn main() -&gt; Result&lt;(), Box&lt;dyn Error&gt;&gt; {
  20. let dirty_string = r#&quot;\&quot;{\\\&quot;key1\\\&quot;:\\\&quot;val1\\\&quot;,\\\&quot;key2\\\&quot;:\\\&quot;val2\\\&quot;}\&quot;&quot;#;
  21. let s = stripslashes(&amp;dirty_string).expect(&quot;stripslashes failed&quot;);
  22. let s: String = serde_json::from_str(&amp;s)?;
  23. let data: Data = serde_json::from_str(&amp;s)?;
  24. println!(&quot;{:?}&quot;, data);
  25. Ok(())
  26. }

This outputs:

  1. 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:

确定