如何为Rust结构体字段禁用JSON格式化输出
解决方案
要实现Span字段的数组在JSON格式化时保持紧凑(不换行),可以通过以下两种方式实现:
方法一:全局禁用数组元素缩进(简单直接)
如果可以接受所有数组类型在JSON pretty输出时都保持紧凑格式,可使用serde_json提供的自定义PrettyFormatter,通过with_indent_array_elements(false)禁用数组元素的自动换行:
use serde::{Deserialize, Serialize}; use serde_json::{ser::PrettyFormatter, Serializer}; use std::io::Write; #[derive(Debug, Deserialize, Serialize)] pub struct Span { pub start: (i32, i32), // (Line, Column) pub end: (i32, i32), // (Line, Column) } fn main() { let span = Span { start: (12, 12), end: (12, 12), }; // 配置Formatter:使用4空格缩进,禁用数组元素换行 let formatter = PrettyFormatter::with_indent(b" ").with_indent_array_elements(false); let mut serializer = Serializer::new(formatter, Vec::new()); span.serialize(&mut serializer).unwrap(); let formatted_json = String::from_utf8(serializer.into_inner().into_inner()).unwrap(); println!("{}", formatted_json); }
输出结果:
{ "start": [12, 12], "end": [12, 12] }
方法二:仅让Span的数组字段紧凑(局部控制)
如果需要其他数组字段保持默认的换行格式,仅让Span的start和end数组紧凑,可以通过自定义序列化逻辑结合serde_json::RawValue实现:
- 首先在
Cargo.toml中启用serde_json的raw_value特性:
[dependencies] serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] }
- 为Span实现自定义
Serializetrait,将start和end序列化为紧凑的原始JSON字符串:
use serde::{Deserialize, Serialize, Serializer}; use serde_json::{Value, RawValue}; #[derive(Debug, Deserialize)] pub struct Span { pub start: (i32, i32), // (Line, Column) pub end: (i32, i32), // (Line, Column) } impl Serialize for Span { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, { // 先将Span转换为通用Value对象 let mut span_value = serde_json::to_value(self) .map_err(serde::ser::Error::custom)?; if let Value::Object(ref mut obj) = span_value { // 处理start字段:转为紧凑JSON字符串后作为原始值写入 if let Some(Value::Array(start_arr)) = obj.get_mut("start") { let compact_start = serde_json::to_string(start_arr) .map_err(serde::ser::Error::custom)?; let raw_start = RawValue::from_string(compact_start) .map_err(serde::ser::Error::custom)?; obj.insert("start".into(), Value::RawValue(raw_start)); } // 处理end字段:同上 if let Some(Value::Array(end_arr)) = obj.get_mut("end") { let compact_end = serde_json::to_string(end_arr) .map_err(serde::ser::Error::custom)?; let raw_end = RawValue::from_string(compact_end) .map_err(serde::ser::Error::custom)?; obj.insert("end".into(), Value::RawValue(raw_end)); } } // 序列化修改后的Value对象 span_value.serialize(serializer) } } // 使用示例 fn main() { let span = Span { start: (12, 12), end: (12, 12), }; let formatted_json = serde_json::to_string_pretty(&span).unwrap(); println!("{}", formatted_json); }
这种方式下,其他数组字段仍会保持默认的换行格式,仅Span的start和end数组以紧凑形式输出。
内容的提问来源于stack exchange,提问作者Mohit Saini
相关产品推荐
相关产品推荐

