英文:
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: &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(())
}
This outputs:
Data { key1: "val1", key2: "val2" }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论