如何用JToken实现Newtonsoft.Json序列化列表的自定义换行格式?
解决Newtonsoft.Json列表元素每行显示10个的格式化需求
我在使用Newtonsoft.Json进行JSON序列化与反序列化时,遇到了列表对象元素的缩进问题。希望列表每行显示10个元素,剩余元素换行展示,请问如何通过JToken实现该需求?
预期输出
"parameters": [ { "description": "EnableTestValues", "defaults": [ 0,1,1,2,3,4,5,6,9,7, 99,12,85,14,66,78 ], "size": [ 1,16 ] }, { "description": "CEC_Emer_Stop_Val", "defaults": [ false ], "size": [ 1,1 ] }, { "description": "CEC_Emer_Stop_Sw", "defaults": [ 252 ], "size": [ 1,1 ] } ]
实际输出
"parameters": [ { "description": "EnableTestValues", "defaults": [ 0, 1, 1, 2, 3, 4, 5, 6, 9, 7, 99, 12, 85, 14, 66, 78 ], "size": [ 1, 16 ] }, { "description": "CEC_Emer_Stop_Val", "defaults": [ false ], "size": [ 1, 1 ] }, { "description": "CEC_Emer_Stop_Sw", "defaults": [ 252 ], "size": [ 1, 1 ] } ]
当前代码
dynamic mdcsJson; using (StreamReader r = new StreamReader(mdcsJsonFilePath)) { string fileContent = System.IO.File.ReadAllText(mdcsJsonFilePath, Encoding.GetEncoding(1250)); mdcsJson = JsonConvert.DeserializeObject(fileContent); } // Updating some values here string strJson = JsonConvert.SerializeObject(mdcsJson)
解决方案
要实现列表每行10个元素的格式化,需要自定义JsonTextWriter控制数组元素的输出逻辑,结合JToken完成序列化:
1. 自定义JsonTextWriter
继承JsonTextWriter,跟踪数组内元素计数,达到10个时自动换行并保持缩进:
public class ArrayPerLineJsonWriter : JsonTextWriter { private int _currentArrayElementCount = 0; private const int ElementsPerLine = 10; private bool _isInsideArray = false; public ArrayPerLineJsonWriter(TextWriter textWriter) : base(textWriter) { Formatting = Formatting.Indented; } public override void WriteStartArray() { base.WriteStartArray(); _isInsideArray = true; _currentArrayElementCount = 0; } public override void WriteEndArray() { base.WriteEndArray(); _isInsideArray = false; } public override void WriteValue(object value) { HandleArrayElement(); base.WriteValue(value); } public override void WriteValue(int value) { HandleArrayElement(); base.WriteValue(value); } public override void WriteValue(bool value) { HandleArrayElement(); base.WriteValue(value); } private void HandleArrayElement() { if (!_isInsideArray) return; if (_currentArrayElementCount > 0) { WriteRaw(","); if (_currentArrayElementCount % ElementsPerLine == 0) { WriteNewLine(); WriteIndent(); } else { WriteRaw(" "); } } _currentArrayElementCount++; } }
2. 结合JToken使用自定义Writer
将dynamic替换为JToken,使用自定义Writer完成序列化:
// 读取并解析为JToken JToken mdcsJson; using (StreamReader r = new StreamReader(mdcsJsonFilePath, Encoding.GetEncoding(1250))) { string fileContent = r.ReadToEnd(); mdcsJson = JToken.Parse(fileContent); } // 执行数据更新逻辑... // 使用自定义Writer序列化 string strJson; using (StringWriter sw = new StringWriter()) { using (var writer = new ArrayPerLineJsonWriter(sw)) { mdcsJson.WriteTo(writer); } strJson = sw.ToString(); }
说明
- 自定义Writer通过
_isInsideArray标记当前是否处于数组内,_currentArrayElementCount统计当前行的元素数量。 - 每写入一个数组元素时,判断是否已达10个,达到则换行并缩进,否则仅添加空格分隔。
- 替换
JsonConvert.DeserializeObject为JToken.Parse,利用JToken的WriteTo方法配合自定义Writer输出符合要求的JSON。
内容的提问来源于stack exchange,提问作者Srusti Thakkar
相关产品推荐
相关产品推荐

