diff --git a/Cargo.lock b/Cargo.lock index c6b9489..2f52279 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1059,12 +1059,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "json" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" - [[package]] name = "language-tags" version = "0.3.2" @@ -1416,7 +1410,6 @@ dependencies = [ "actix-web", "bytes", "futures", - "json", "lazy_static", "log", "pdf", diff --git a/Cargo.toml b/Cargo.toml index 4198a07..2104ce5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,6 @@ actix-files = "0.6.0" actix-web = "4.0.1" bytes = "1.1" futures = "0.3" -json = "0.12.4" lazy_static = "1.4" log = "0.4.16" pdf = "0.8" diff --git a/src/serialize.rs b/src/serialize.rs index 5de17be..ac8ef56 100644 --- a/src/serialize.rs +++ b/src/serialize.rs @@ -66,7 +66,7 @@ impl DataFormat for Csv { fn header(dataset: &DataSet) -> SerializationChunk { let mut header = String::from("Date"); for column in dataset.columns.iter() { - write!(&mut header, ",{}", column)?; + write!(&mut header, r#","{}""#, column.replace('"', r#""""#))?; } writeln!(&mut header)?; Ok(header) @@ -97,7 +97,7 @@ impl DataFormat for Json { fn header(dataset: &DataSet) -> SerializationChunk { let mut header = String::from(r#"{"columns":["Date""#); for column in dataset.columns.iter() { - write!(&mut header, ",{}", json::stringify(column.as_str()))?; + write!(&mut header, ",{}", escaped_json_string(column.as_str()))?; } write!(&mut header, r#"],"rows":["#)?; Ok(header) @@ -115,7 +115,7 @@ impl DataFormat for Json { )?; for column in dataset.columns.iter() { if let Some(val) = datapoint.values.get(column) { - write!(&mut row, ",{}:{}", json::stringify(column.as_str()), val)?; + write!(&mut row, ",{}:{}", escaped_json_string(column.as_str()), val)?; } } row += "}"; @@ -125,3 +125,20 @@ impl DataFormat for Json { const ROW_SEPARATOR: &'static str = ","; const END: &'static str = "]}"; } + +fn escaped_json_string(s: &str) -> String { + s.chars().fold(String::from(r#"""#), |mut acc, c| { + match c { + '"' => acc.push_str(r#"\""#), + '\\' => acc.push_str(r"\\"), + '\t' => acc.push_str(r"\t"), + '\n' => acc.push_str(r"\n"), + _ => if c.is_ascii_control() { + acc.push_str(&format!(r"\u{:04X}", c as u32)) + } else { + acc.push(c) + } + } + acc + }) + r#"""# +}