Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid double '\' escape when using serde_json in Rust?

Is it somehow possible to create a String Value from bytes WITHOUT doubling the backslash character in SERDE?

Playground:

use serde_json::json;
use serde_json::{Value};
use std::str;

fn main() {
    let bytes = [79, 66, 88, 90, 70, 65, 68, 54, 80, 54, 76, 65, 92,
                117, 48, 48, 49, 102, 50, 50, 50, 50, 71, 66, 54, 87,
                65, 65, 85, 52, 54, 87, 87, 86, 92, 117, 48, 48, 49, 102,
                123, 92, 34, 36, 116, 122, 92, 34, 58, 92, 34, 69, 117, 114,
                111, 112, 101, 47, 66, 101, 114, 108, 105, 110, 92, 34, 125];
    let string = str::from_utf8(&bytes).unwrap();
    let json_string = json!(&string);
    let json_string2 = Value::String(string.to_string());
    println!("string: {}",string);
    println!("json 1: {}",json_string);
    println!("json 2: {}",json_string2);
}
like image 203
Marko Seidenglanz Avatar asked Sep 13 '25 21:09

Marko Seidenglanz


1 Answers

You have a string that already contains escapes. To avoid the backslash itself getting escaped, you can interpret the escapes yourself before passing the string to serde. For example, using the unescape crate to interpret escapes, the code would look like this:

use serde_json::json;
use std::str;
use unescape::unescape;

fn main() {
    let bytes = [
        79, 66, 88, 90, 70, 65, 68, 54, 80, 54, 76, 65, 92, 117, 48, 48, 49, 102, 50, 50, 50, 50,
        71, 66, 54, 87, 65, 65, 85, 52, 54, 87, 87, 86, 92, 117, 48, 48, 49, 102, 123, 92, 34, 36,
        116, 122, 92, 34, 58, 92, 34, 69, 117, 114, 111, 112, 101, 47, 66, 101, 114, 108, 105, 110,
        92, 34, 125,
    ];
    let string_with_escapes = str::from_utf8(&bytes).unwrap();
    let unescaped_string = unescape(string_with_escapes).unwrap();
    let json_string = json!(&unescaped_string);
    println!("string with escapes: {}", string_with_escapes);
    println!("string without escapes: {}", unescaped_string);
    println!("json: {}", json_string);
}

Output (but note that string without escapes contains some unprintable chars that are not rendered):

string with escapes: OBXZFAD6P6LA\u001f2222GB6WAAU46WWV\u001f{\"$tz\":\"Europe/Berlin\"}
string without escapes: OBXZFAD6P6LA2222GB6WAAU46WWV{"$tz":"Europe/Berlin"}
json: "OBXZFAD6P6LA\u001f2222GB6WAAU46WWV\u001f{\"$tz\":\"Europe/Berlin\"}"

If you wish to avoid depending on unescape (which hasn't been updated since its inception in 2016), you could even let serde_json do the unescaping:

fn unescape(s: &str) -> serde_json::Result<String> {
    serde_json::from_str(&format!("\"{}\"", s))
}

Playground

like image 128
user4815162342 Avatar answered Sep 15 '25 14:09

user4815162342