use std::path::Path;
use once_cell::sync::Lazy;
use regex::Regex;
use crate::{load_write_utils, Quotes};
const SUPPORTED_KEY_CHARS_REGEX_STR: &str = r#"A-Za-z0-9`~!@#$%€^&*()\-_=+\\|;"'.<>/?\s"#;
pub fn json_convert_with_to_without_keyquotes(path: &Path) {
let json = match load_write_utils::load_json(path) {
Ok(val) => val,
Err(err) => {
eprintln!("{}", err);
return;
}
};
let unquoted_json = json_remove_key_quotes(&json);
match load_write_utils::write_json(path, &json_unescape_ctrlchars(&unquoted_json)) {
Ok(()) => (),
Err(err) => {
eprintln!("{}", err);
return;
}
}
}
pub fn json_convert_without_to_with_keyquotes(path: &Path, quote_type: Quotes) {
let json = match load_write_utils::load_json(path) {
Ok(val) => val,
Err(err) => {
eprintln!("{}", err);
return;
}
};
let keyquoted_json = json_add_key_quotes(&json, quote_type);
match load_write_utils::write_json(path, &json_escape_ctrlchars(&keyquoted_json)) {
Ok(()) => (),
Err(err) => {
eprintln!("{}", err);
return;
}
}
}
pub fn json_add_key_quotes(json: &str, quote_type: Quotes) -> String {
let single_quoted_string_val_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<prevchar_key>[^"'][\s]*)(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])(?P<val>:\s*?'[\s\S]*?')"#),
)
.unwrap()
});
let json_single_quoted_string_passed = single_quoted_string_val_regex.replace_all(
json,
"$prevchar_key".to_string() + quote_type.as_str() + "$key" + quote_type.as_str() + "$val",
);
let double_quoted_string_val_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<prevchar_key>[^"'][\s]*)(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])(?P<val>:\s*?"[\s\S]*?")"#),
)
.unwrap()
});
let json_double_quoted_string_passed = double_quoted_string_val_regex.replace_all(
&json_single_quoted_string_passed,
"$prevchar_key".to_string() + quote_type.as_str() + "$key" + quote_type.as_str() + "$val",
);
let object_val_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])(?P<val>:\s*?[{\[])"#),
)
.unwrap()
});
let json_object_passed = object_val_regex.replace_all(
&json_double_quoted_string_passed,
quote_type.as_str().to_string() + "$key" + quote_type.as_str() + "$val",
);
let number_val_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<before>[\[,{]\s*?)(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])(?P<after>:\s*?[\d\-\.])"#),
)
.unwrap()
});
let json_number_passed = number_val_regex.replace_all(
&json_object_passed,
"$before".to_string() + quote_type.as_str() + "$key" + quote_type.as_str() + "$after",
);
let null_bools_val_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<before>[\[,{]\s*?)(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])(?P<after>:\s*?(?:null|true|false))"#),
)
.unwrap()
});
let json_null_bools_passed = null_bools_val_regex.replace_all(
&json_number_passed,
"$before".to_string() + quote_type.as_str() + "$key" + quote_type.as_str() + "$after",
);
return json_null_bools_passed.to_string();
}
pub fn json_remove_key_quotes(json: &str) -> String {
let single_quotes_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<before>[{\[,][\s]*)'(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?)'(?P<after>\s*?:)"#),
)
.unwrap()
});
let json_single_quotes_passed = single_quotes_regex.replace_all(json, "$before$key$after");
let double_quotes_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<before>[{\[,][\s]*)"(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?)"(?P<after>\s*?:)"#),
)
.unwrap()
});
let json_double_quotes_passed =
double_quotes_regex.replace_all(&json_single_quotes_passed, "$before$key$after");
return json_double_quotes_passed.to_string();
}
pub fn json_escape_ctrlchars(json: &str) -> String {
let mut new_json = json.to_owned();
for _n in 0..2 {
let singlequoted_string_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<prevchar_key>[^"'][\s]*)'(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])'(?P<val>\s*?:\s*?'[\s\S]*?')"#),
)
.unwrap()
});
for cap in singlequoted_string_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\r", ""), 1);
new_json =
new_json.replacen(cap_match, &cap_match.replace("\t", "").replace("\t", ""), 1);
}
let singlequoted_string_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<prevchar_key>[^"'][\s]*)"(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])"(?P<val>\s*?:\s*?'[\s\S]*?')"#),
)
.unwrap()
});
for cap in singlequoted_string_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\r", ""), 1);
new_json =
new_json.replacen(cap_match, &cap_match.replace("\t", "").replace("\t", ""), 1);
}
let doublequoted_string_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<prevchar_key>[^"'][\s]*)'(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])'(?P<val>\s*?:\s*?"[\s\S]*?")"#),
)
.unwrap()
});
for cap in doublequoted_string_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\r", ""), 1);
new_json =
new_json.replacen(cap_match, &cap_match.replace("\t", "").replace("\t", ""), 1);
}
let doublequoted_string_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<prevchar_key>[^"'][\s]*)"(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])"(?P<val>\s*?:\s*?"[\s\S]*?")"#),
)
.unwrap()
});
for cap in doublequoted_string_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\r", ""), 1);
new_json =
new_json.replacen(cap_match, &cap_match.replace("\t", "").replace("\t", ""), 1);
new_json =
new_json.replacen(cap_match, &cap_match.replace("\t", "").replace("\t", ""), 1);
}
let object_key_regex = Lazy::new(|| {
Regex::new(
&(r#"'(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])'(?P<val>\s*?:\s*?[{\[])"#),
)
.unwrap()
});
for cap in object_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\r", ""), 1);
new_json =
new_json.replacen(cap_match, &cap_match.replace("\t", "").replace("\t", ""), 1);
}
let object_key_regex = Lazy::new(|| {
Regex::new(
&(r#""(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])"(?P<val>\s*?:\s*?[{\[])"#),
)
.unwrap()
});
for cap in object_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\r", ""), 1);
new_json =
new_json.replacen(cap_match, &cap_match.replace("\t", "").replace("\t", ""), 1);
}
let number_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<before>[\[,{]\s*?)'(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])'(?P<after>\s*?:\s*?[\d\-\.])"#),
)
.unwrap()
});
for cap in number_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\r", ""), 1);
new_json =
new_json.replacen(cap_match, &cap_match.replace("\t", "").replace("\t", ""), 1);
}
let number_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<before>[\[,{]\s*?)"(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])"(?P<after>\s*?:\s*?[\d\-\.])"#),
)
.unwrap()
});
for cap in number_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\r", ""), 1);
new_json =
new_json.replacen(cap_match, &cap_match.replace("\t", "").replace("\t", ""), 1);
}
let null_boolean_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<before>[\[,{]\s*?)'(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])'(?P<after>\s*?:\s*?(?:null|true|false))"#),
)
.unwrap()
});
for cap in null_boolean_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\r", ""), 1);
new_json =
new_json.replacen(cap_match, &cap_match.replace("\t", "").replace("\t", ""), 1);
}
let null_boolean_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<before>[\[,{]\s*?)"(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])"(?P<after>\s*?:\s*?(?:null|true|false))"#),
)
.unwrap()
});
for cap in null_boolean_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\r", ""), 1);
new_json =
new_json.replacen(cap_match, &cap_match.replace("\t", "").replace("\t", ""), 1);
}
let singlequoted_string_value_regex =
Lazy::new(|| Regex::new(r#":[\s]*?'((?:[^'\\]|\\.)*)'"#).unwrap());
for cap in singlequoted_string_value_regex.captures_iter(&new_json.clone()) {
new_json = new_json.replacen(&cap[1], &cap[1].replace("\r", "\\r"), 1);
new_json = new_json.replacen(&cap[1], &cap[1].replace("\n", "\\n"), 1);
new_json = new_json.replacen(&cap[1], &cap[1].replace("\t", "\\t"), 1);
}
let doublequoted_string_value_regex =
Lazy::new(|| Regex::new(r#":[\s]*?"((?:[^"\\]|\\.)*)""#).unwrap());
for cap in doublequoted_string_value_regex.captures_iter(&new_json.clone()) {
new_json = new_json.replacen(&cap[1], &cap[1].replace("\r", "\\r"), 1);
new_json = new_json.replacen(&cap[1], &cap[1].replace("\n", "\\n"), 1);
new_json = new_json.replacen(&cap[1], &cap[1].replace("\t", "\\t"), 1);
}
}
new_json
}
pub fn json_unescape_ctrlchars(json: &str) -> String {
let mut new_json = json.to_owned();
for _n in 0..2 {
let singlequoted_string_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<prevchar_key>[^"'][\s]*)(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])(?P<val>\s*?:\s*?'[\s\S]*?')"#),
)
.unwrap()
});
for cap in singlequoted_string_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\\r", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\\t", ""), 1);
}
let doublequoted_string_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<prevchar_key>[^"'][\s]*)(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])(?P<val>\s*?:\s*?"[\s\S]*?")"#),
)
.unwrap()
});
for cap in doublequoted_string_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\\r", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\\t", ""), 1);
}
let object_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])(?P<val>\s*?:\s*?[{\[])"#),
)
.unwrap()
});
for cap in object_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\\r", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\\t", ""), 1);
}
let number_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<before>[\[,{]\s*?)(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])(?P<after>\s*?:\s*?[\d\-\.])"#),
)
.unwrap()
});
for cap in number_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\\r", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\\t", ""), 1);
}
let null_boolean_key_regex = Lazy::new(|| {
Regex::new(
&(r#"(?P<before>[\[,{]\s*?)(?P<key>["#.to_string()
+ SUPPORTED_KEY_CHARS_REGEX_STR
+ r#"]*?[^"'])(?P<after>\s*?:\s*?(?:null|true|false))"#),
)
.unwrap()
});
for cap in null_boolean_key_regex.captures_iter(&new_json.clone()) {
let cap_match = cap.name("key").unwrap().as_str();
new_json = new_json.replacen(cap_match, &cap_match.replace("\\r", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\\n", ""), 1);
new_json = new_json.replacen(cap_match, &cap_match.replace("\\t", ""), 1);
}
let singlequoted_string_value_regex =
Lazy::new(|| Regex::new(r#":[\s]*?'((?:[^'\\]|\\.)*)'"#).unwrap());
for cap in singlequoted_string_value_regex.captures_iter(&new_json.clone()) {
new_json = new_json.replacen(&cap[1], &cap[1].replace("\\r", "\r"), 1);
new_json = new_json.replacen(&cap[1], &cap[1].replace("\\n", "\n"), 1);
new_json = new_json.replacen(&cap[1], &cap[1].replace("\\t", "\t"), 1);
}
let doublequoted_string_value_regex =
Lazy::new(|| Regex::new(r#":[\s]*?"((?:[^"\\]|\\.)*)""#).unwrap());
for cap in doublequoted_string_value_regex.captures_iter(&new_json.clone()) {
new_json = new_json.replacen(&cap[1], &cap[1].replace("\\r", "\r"), 1);
new_json = new_json.replacen(&cap[1], &cap[1].replace("\\n", "\n"), 1);
new_json = new_json.replacen(&cap[1], &cap[1].replace("\\t", "\t"), 1);
}
}
new_json
}
#[cfg(test)]
mod tests {
use crate::{json_key_quote_utils, load_write_utils, Quotes};
use std::path::Path;
const SUPPORTED_KEY_CHARS: &str = r#"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%€^&*()-_=+\|;"'.<>/?"#;
const SUPPORTED_VALUE_CHARS: &str = r#"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%€^&*()-_=+\|:;"'.<>/?"#;
#[test]
fn test_json_convert_without_to_with_keyquotes() {
let path = Path::new("./tmp_without_keyquotes");
std::fs::copy(
"./test_resources/Test_without_keyquotes.json",
"./tmp_without_keyquotes",
)
.unwrap();
json_key_quote_utils::json_convert_without_to_with_keyquotes(
path,
crate::Quotes::DoubleQuote,
);
let converted_file_contents = load_write_utils::load_json(path).unwrap();
let expected_file_contents =
load_write_utils::load_json(Path::new("./test_resources/Test_with_keyquotes.json"))
.unwrap();
assert!(converted_file_contents == expected_file_contents);
std::fs::remove_file("./tmp_without_keyquotes").unwrap();
}
#[test]
fn test_json_convert_with_to_without_keyquotes() {
let path = Path::new("./tmp_with_keyquotes");
std::fs::copy(
"./test_resources/Test_with_keyquotes.json",
"./tmp_with_keyquotes",
)
.unwrap();
json_key_quote_utils::json_convert_with_to_without_keyquotes(path);
let converted_file_contents = load_write_utils::load_json(path).unwrap();
let expected_file_contents =
load_write_utils::load_json(Path::new("./test_resources/Test_without_keyquotes.json"))
.unwrap();
assert!(converted_file_contents == expected_file_contents);
std::fs::remove_file("./tmp_with_keyquotes").unwrap();
}
#[test]
fn test_json_add_key_quotes_single_quote_add_supported_characters() {
let supported_key_chars = SUPPORTED_KEY_CHARS.replacen(r#"'"#, r#"\'"#, 1);
let supported_value_chars = SUPPORTED_VALUE_CHARS.replacen(r#"'"#, r#"\'"#, 1);
let json =
r#"{"#.to_string() + &supported_key_chars + r#": '"# + &supported_value_chars + r#"'}"#;
let expected = r#"{'"#.to_string()
+ &supported_key_chars
+ r#"': '"#
+ &supported_value_chars
+ r#"'}"#;
let actual = json_key_quote_utils::json_add_key_quotes(&json, Quotes::SingleQuote);
let actual_second_pass =
json_key_quote_utils::json_add_key_quotes(&actual, Quotes::SingleQuote);
assert_eq!(expected, actual);
assert_eq!(expected, actual_second_pass);
}
#[test]
fn test_json_add_key_quotes_double_quote_add_supported_characters() {
let supported_key_chars = SUPPORTED_KEY_CHARS.replacen(r#"""#, r#"\""#, 1);
let supported_value_chars = SUPPORTED_VALUE_CHARS.replacen(r#"""#, r#"\""#, 1);
let json =
r#"{"#.to_string() + &supported_key_chars + r#": ""# + &supported_value_chars + r#""}"#;
let expected = r#"{""#.to_string()
+ &supported_key_chars
+ r#"": ""#
+ &supported_value_chars
+ r#""}"#;
let actual = json_key_quote_utils::json_add_key_quotes(&json, Quotes::DoubleQuote);
let actual_second_pass =
json_key_quote_utils::json_add_key_quotes(&actual, Quotes::DoubleQuote);
assert_eq!(expected, actual);
assert_eq!(expected, actual_second_pass);
}
#[test]
fn test_json_remove_key_quotes_single_quoted_supported_characters() {
let supported_key_chars = SUPPORTED_KEY_CHARS.replacen(r#"'"#, r#"\'"#, 1);
let supported_value_chars = SUPPORTED_VALUE_CHARS.replacen(r#"'"#, r#"\'"#, 1);
let json = r#"{'"#.to_string()
+ &supported_key_chars
+ r#"': ""#
+ &supported_value_chars
+ r#""}"#;
let expected =
r#"{"#.to_string() + &supported_key_chars + r#": ""# + &supported_value_chars + r#""}"#;
let actual = json_key_quote_utils::json_remove_key_quotes(&json);
let actual_second_pass = json_key_quote_utils::json_remove_key_quotes(&actual);
assert_eq!(expected, actual);
assert_eq!(expected, actual_second_pass);
}
#[test]
fn test_json_remove_key_quotes_double_quoted_supported_characters() {
let supported_key_chars = SUPPORTED_KEY_CHARS.replacen(r#"""#, r#"\""#, 1);
let supported_value_chars = SUPPORTED_VALUE_CHARS.replacen(r#"""#, r#"\""#, 1);
let json = r#"{""#.to_string()
+ &supported_key_chars
+ r#"": ""#
+ &supported_value_chars
+ r#""}"#;
let expected =
r#"{"#.to_string() + &supported_key_chars + r#": ""# + &supported_value_chars + r#""}"#;
let actual = json_key_quote_utils::json_remove_key_quotes(&json);
let actual_second_pass = json_key_quote_utils::json_remove_key_quotes(&actual);
assert_eq!(expected, actual);
assert_eq!(expected, actual_second_pass);
}
#[test]
fn test_json_escape_ctrlchars_single_quoted_supported_characters() {
let supported_key_chars = SUPPORTED_KEY_CHARS.replacen(r#"'"#, r#"\'"#, 1);
let supported_value_chars = SUPPORTED_VALUE_CHARS.replacen(r#"'"#, r#"\'"#, 1);
let key = supported_key_chars.to_string();
let value = supported_value_chars
.replacen(
"A", r#"A
"#, 1,
)
.replacen("B", r#"B "#, 1);
let expected_key = supported_key_chars.to_string();
let expected_value = supported_value_chars
.replacen("A", r#"A\n"#, 1)
.replacen("B", r#"B\t"#, 1);
let json = r#"{'"#.to_string() + &key + r#"': '"# + &value + r#"'}"#;
let expected = r#"{'"#.to_string() + &expected_key + r#"': '"# + &expected_value + r#"'}"#;
let actual = json_key_quote_utils::json_escape_ctrlchars(&json);
let actual_second_pass = json_key_quote_utils::json_escape_ctrlchars(&actual);
assert_eq!(expected, actual);
assert_eq!(expected, actual_second_pass);
}
#[test]
fn test_json_escape_ctrlchars_double_quoted_supported_characters() {
let supported_key_chars = SUPPORTED_KEY_CHARS.replacen(r#"""#, r#"\""#, 1);
let supported_value_chars = SUPPORTED_VALUE_CHARS.replacen(r#"""#, r#"\""#, 1);
let key = supported_key_chars.to_string();
let value = supported_value_chars
.replacen(
"A", r#"A
"#, 1,
)
.replacen("B", r#"B "#, 1);
let expected_key = supported_key_chars.to_string();
let expected_value = supported_value_chars
.replacen("A", r#"A\n"#, 1)
.replacen("B", r#"B\t"#, 1);
let json = r#"{""#.to_string() + &key + r#"": ""# + &value + r#""}"#;
let expected = r#"{""#.to_string() + &expected_key + r#"": ""# + &expected_value + r#""}"#;
let actual = json_key_quote_utils::json_escape_ctrlchars(&json);
let actual_second_pass = json_key_quote_utils::json_escape_ctrlchars(&actual);
assert_eq!(expected, actual);
assert_eq!(expected, actual_second_pass);
}
#[test]
fn test_json_escape_ctrlchars_unquoted_keys_supported_characters() {
let supported_value_chars = SUPPORTED_VALUE_CHARS.replacen(r#"""#, r#"\""#, 1);
let key = SUPPORTED_KEY_CHARS
.replacen(
"A", r#"A
"#, 1,
)
.replacen("B", r#"B "#, 1);
let value = supported_value_chars
.replacen(
"A", r#"A
"#, 1,
)
.replacen("B", r#"B "#, 1);
let expected_value = supported_value_chars
.replacen("A", r#"A\n"#, 1)
.replacen("B", r#"B\t"#, 1);
let json = r#"{"#.to_string() + &key + r#": ""# + &value + r#""}"#;
let expected = r#"{"#.to_string() + &key + r#": ""# + &expected_value + r#""}"#;
let actual = json_key_quote_utils::json_escape_ctrlchars(&json);
let actual_second_pass = json_key_quote_utils::json_escape_ctrlchars(&actual);
assert_eq!(expected, actual);
assert_eq!(expected, actual_second_pass);
}
#[test]
fn test_json_unescape_ctrlchars_single_quoted_supported_characters() {
let supported_key_chars = SUPPORTED_KEY_CHARS.replacen(r#"'"#, r#"\'"#, 1);
let supported_value_chars = SUPPORTED_VALUE_CHARS.replacen(r#"'"#, r#"\'"#, 1);
let key = supported_key_chars.to_string();
let value = supported_value_chars
.replacen("A", r#"A\n"#, 1)
.replacen("B", r#"B\t"#, 1);
let expected_key = supported_key_chars.to_string();
let expected_value = supported_value_chars
.replacen(
"A", r#"A
"#, 1,
)
.replacen("B", r#"B "#, 1);
let json = r#"{"#.to_string() + &key + r#": '"# + &value + r#"'}"#;
let expected = r#"{"#.to_string() + &expected_key + r#": '"# + &expected_value + r#"'}"#;
let actual = json_key_quote_utils::json_unescape_ctrlchars(&json);
let actual_second_pass = json_key_quote_utils::json_unescape_ctrlchars(&actual);
assert_eq!(expected, actual);
assert_eq!(expected, actual_second_pass);
}
#[test]
fn test_json_unescape_ctrlchars_double_quoted_supported_characters() {
let supported_key_chars = SUPPORTED_KEY_CHARS.replacen(r#"""#, r#"\""#, 1);
let supported_value_chars = SUPPORTED_VALUE_CHARS.replacen(r#"""#, r#"\""#, 1);
let key = supported_key_chars.to_string();
let value = supported_value_chars
.replacen("A", r#"A\n"#, 1)
.replacen("B", r#"B\t"#, 1);
let expected_key = supported_key_chars.to_string();
let expected_value = supported_value_chars
.replacen(
"A", r#"A
"#, 1,
)
.replacen("B", r#"B "#, 1);
let json = r#"{"#.to_string() + &key + r#": ""# + &value + r#""}"#;
let expected = r#"{"#.to_string() + &expected_key + r#": ""# + &expected_value + r#""}"#;
let actual = json_key_quote_utils::json_unescape_ctrlchars(&json);
let actual_second_pass = json_key_quote_utils::json_unescape_ctrlchars(&actual);
assert_eq!(expected, actual);
assert_eq!(expected, actual_second_pass);
}
#[test]
fn test_json_unescape_ctrlchars_double_quoted_keys_supported_characters() {
let supported_value_chars = SUPPORTED_VALUE_CHARS.replacen(r#"""#, r#"\""#, 1);
let key = SUPPORTED_KEY_CHARS
.replacen("A", r#"A\n"#, 1)
.replacen("B", r#"B\t"#, 1);
let value = supported_value_chars
.replacen("A", r#"A\n"#, 1)
.replacen("B", r#"B\t"#, 1);
let expected_value = supported_value_chars
.replacen(
"A", r#"A
"#, 1,
)
.replacen("B", r#"B "#, 1);
let json = r#"{""#.to_string() + &key + r#"": ""# + &value + r#""}"#;
let expected = r#"{""#.to_string() + &key + r#"": ""# + &expected_value + r#""}"#;
let actual = json_key_quote_utils::json_unescape_ctrlchars(&json);
let actual_second_pass = json_key_quote_utils::json_unescape_ctrlchars(&actual);
assert_eq!(expected, actual);
assert_eq!(expected, actual_second_pass);
}
}