use std::io;
use serde::Serialize;
use serde_json::{
ser::{Formatter, Serializer},
Value,
};
struct PythonDefaultFormatter;
impl Formatter for PythonDefaultFormatter {
fn begin_object_value<W: ?Sized + io::Write>(&mut self, w: &mut W) -> io::Result<()> {
w.write_all(b": ")
}
fn begin_object_key<W: ?Sized + io::Write>(
&mut self,
w: &mut W,
first: bool,
) -> io::Result<()> {
if first {
Ok(())
} else {
w.write_all(b", ")
}
}
fn begin_array_value<W: ?Sized + io::Write>(
&mut self,
w: &mut W,
first: bool,
) -> io::Result<()> {
if first {
Ok(())
} else {
w.write_all(b", ")
}
}
}
pub(crate) fn to_string(value: &Value) -> String {
let mut buf = Vec::new();
let mut ser = Serializer::with_formatter(&mut buf, PythonDefaultFormatter);
if value.serialize(&mut ser).is_err() {
return "null".to_string();
}
String::from_utf8(buf).unwrap_or_else(|_| "null".to_string())
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::*;
#[test]
fn matches_python_json_dumps() {
let v = json!({"city": "杭州", "count": 42, "flags": [1, true, null], "x": 1.5});
assert_eq!(
to_string(&v),
r#"{"city": "杭州", "count": 42, "flags": [1, true, null], "x": 1.5}"#
);
}
#[test]
fn empty_containers_and_nested_json_strings() {
assert_eq!(to_string(&json!({})), "{}");
assert_eq!(to_string(&json!([])), "[]");
assert_eq!(
to_string(&json!({"query": "{\"a\": 1}", "limit": 2})),
r#"{"query": "{\"a\": 1}", "limit": 2}"#
);
}
}