use serde::Serialize;
use std::fmt;
#[inline]
pub fn write_json<T: Serialize + ?Sized>(value: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match serde_json::to_string(value) {
Ok(json) => f.write_str(&json),
Err(e) => write!(f, "Error serializing to JSON: {e}"),
}
}
#[inline]
pub fn write_json_pretty<T: Serialize + ?Sized>(
value: &T,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
match serde_json::to_string_pretty(value) {
Ok(json) => f.write_str(&json),
Err(e) => write!(f, "Error serializing to JSON: {e}"),
}
}
#[macro_export]
macro_rules! impl_json_display {
($($ty:ty),+ $(,)?) => {
$(
impl ::std::fmt::Display for $ty {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
$crate::utils::json_format::write_json(self, f)
}
}
)+
};
}
#[macro_export]
macro_rules! impl_json_debug {
($($ty:ty),+ $(,)?) => {
$(
impl ::std::fmt::Debug for $ty {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
$crate::utils::json_format::write_json(self, f)
}
}
)+
};
}
#[macro_export]
macro_rules! impl_json_debug_pretty {
($($ty:ty),+ $(,)?) => {
$(
impl ::std::fmt::Debug for $ty {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
$crate::utils::json_format::write_json_pretty(self, f)
}
}
)+
};
}
#[cfg(test)]
mod tests {
use serde::ser::Error as _;
use serde::{Serialize, Serializer};
#[derive(Serialize)]
struct Sample {
name: &'static str,
value: u32,
}
crate::impl_json_display!(Sample);
crate::impl_json_debug_pretty!(Sample);
#[derive(Serialize)]
struct Compact {
flag: bool,
}
crate::impl_json_debug!(Compact);
struct Unserializable;
impl Serialize for Unserializable {
fn serialize<S: Serializer>(&self, _serializer: S) -> Result<S::Ok, S::Error> {
Err(S::Error::custom("refused"))
}
}
crate::impl_json_display!(Unserializable);
crate::impl_json_debug!(Unserializable);
#[test]
fn test_json_display_sample_writes_compact_json() {
let sample = Sample {
name: "a",
value: 1,
};
assert_eq!(sample.to_string(), r#"{"name":"a","value":1}"#);
}
#[test]
fn test_json_debug_pretty_sample_writes_indented_json() {
let sample = Sample {
name: "a",
value: 1,
};
assert_eq!(
format!("{sample:?}"),
"{\n \"name\": \"a\",\n \"value\": 1\n}"
);
}
#[test]
fn test_json_debug_compact_writes_compact_json() {
assert_eq!(format!("{:?}", Compact { flag: true }), r#"{"flag":true}"#);
}
#[test]
fn test_json_display_serialization_failure_writes_the_reason() {
assert_eq!(
Unserializable.to_string(),
"Error serializing to JSON: refused"
);
assert_eq!(
format!("{Unserializable:?}"),
"Error serializing to JSON: refused"
);
}
}