use std::io::{self, Write};
use colored::Colorize;
pub fn format_response(out: &mut dyn Write, value: &serde_json::Value) -> io::Result<()> {
let pretty = serde_json::to_string_pretty(value).unwrap_or_else(|_| value.to_string());
colorize_json(out, &pretty)
}
fn colorize_json(out: &mut dyn Write, json_str: &str) -> io::Result<()> {
for line in json_str.lines() {
let trimmed = line.trim();
if matches!(trimmed, "{" | "}" | "[" | "]" | "," | "}," | "],") {
writeln!(out, "{}", line.white().bold())?;
continue;
}
if let Some(colon_pos) = line.find(':') {
let key = &line[..colon_pos];
let value = line[colon_pos + 1..].trim();
write!(out, "{}", key.cyan().bold())?;
write!(out, ":")?;
if value.ends_with('{') || value.ends_with('[') {
let without_bracket = value.trim_end_matches(['{', '[']);
if !without_bracket.is_empty() {
write!(out, "{without_bracket}")?;
}
let bracket = &value[without_bracket.len()..];
writeln!(out, "{}", bracket.white().bold())?;
continue;
}
if value.ends_with('}')
|| value.ends_with(']')
|| value.ends_with("},")
|| value.ends_with("],")
{
let last_bracket = value.rfind(['}', ']']).unwrap_or(value.len());
if last_bracket > 0 {
let before = &value[..last_bracket];
let bracket_part = &value[last_bracket..];
write_colorized_value(out, before)?;
write!(out, "{}", bracket_part.white().bold())?;
writeln!(out)?;
} else {
writeln!(out, "{}", value.white().bold())?;
}
continue;
}
write_colorized_value_ln(out, value)?;
} else {
write_colorized_value_ln(out, line)?;
}
}
Ok(())
}
fn write_colorized_value_ln(out: &mut dyn Write, value: &str) -> io::Result<()> {
write_colorized_value(out, value)?;
writeln!(out)
}
fn write_colorized_value(out: &mut dyn Write, value: &str) -> io::Result<()> {
let trimmed = value.trim();
if (trimmed.starts_with('"') && trimmed.ends_with('"'))
|| (trimmed.starts_with('"') && trimmed.ends_with("\","))
{
write!(out, "{}", value.green())
} else if matches!(trimmed, "true" | "false" | "true," | "false,") {
write!(out, "{}", value.magenta())
} else if matches!(trimmed, "null" | "null,") {
write!(out, "{}", value.red())
} else if trimmed.starts_with('{') || trimmed.starts_with('[') {
write!(out, "{}", value.white().bold())
} else {
write!(out, "{}", value.yellow())
}
}