You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用System.Text.Json序列化时如何限制缩进深度?

如何在System.Text.Json序列化时限制缩进深度

我复用了一个原本针对Newtonsoft.Json的问题,现在想应用到System.Text.Json上:使用System.Text.Json序列化对象时,能否在达到指定深度后停止缩进?

比如针对下面的对象(清单1),能否通过继承JsonConverter或JsonWriter类,只缩进至特定层级,得到输出2或输出3的结果,而非全缩进的输出1?

清单1

var items = new[] {
    new { Name = "John",
          Age = 5,
          Address = new { Home = "No. 123, Oak Street", Email = "john@mail.com" },
          Extra = new { Serials = new[] { 20, 30, 40, 50 } }
    },
    new { Name = "Jean",
          Age = 2,
          Address = new { Home = "No. 321, Cliff Road", Email = "jean@mail.com" },
          Extra = new { Serials = new[] { 25, 35, 45, 55 } }
    }
};

输出1:完全缩进

[
  {
    "Name": "John",
    "Age": 5,
    "Address": {
      "Home": "No. 123, Oak Street",
      "Email": "john@mail.com"
    },
    "Extra": {
      "Serials": [
        20,
        30,
        40,
        50
      ]
    }
  },
  {
    "Name": "Jean",
    "Age": 2,
    "Address": {
      "Home": "No. 321, Cliff Road",
      "Email": "jean@mail.com"
    },
    "Extra": {
      "Serials": [
        25,
        35,
        45,
        55
      ]
    }
  }
]

输出2:缩进至两层深度

[
  {
    "Name": "John",
    "Age": 5,
    "Address": { "Home": "No. 123, Oak Street", "Email": "john@mail.com" },
    "Extra": { "Serials": [ 20, 30, 40, 50 ] }
  },
  {
    "Name": "Jean",
    "Age": 2,
    "Address": { "Home": "No. 321, Cliff Road", "Email": "jean@mail.com" },
    "Extra": { "Serials": [ 25, 35, 45, 55 ] }
  }
]

输出3:缩进至三层深度

[
  {
    "Name": "John",
    "Age": 5,
    "Address": {
      "Home": "No. 123, Oak Street",
      "Email": "john@mail.com"
    },
    "Extra": {
      "Serials": [ 20, 30, 40, 50 ]
    }
  },
  {
    "Name": "Jean",
    "Age": 2,
    "Address": {
      "Home": "No. 321, Cliff Road",
      "Email": "jean@mail.com"
    },
    "Extra": {
      "Serials": [ 25, 35, 45, 55 ]
    }
  }
]

解决方案:自定义LimitedIndentJsonWriter

System.Text.Json没有内置的缩进深度限制功能,我们可以通过继承Utf8JsonWriter来实现需求,核心思路是跟踪当前序列化深度,超过设定值时自动切换为紧凑格式。

1. 实现自定义JsonWriter

public class LimitedIndentJsonWriter : Utf8JsonWriter
{
    private readonly int _maxIndentDepth;
    private int _currentDepth = 0;
    private readonly JsonWriterOptions _originalOptions;

    public LimitedIndentJsonWriter(Stream stream, JsonWriterOptions options, int maxIndentDepth)
        : base(stream, options)
    {
        _maxIndentDepth = maxIndentDepth;
        _originalOptions = options;
    }

    public override void WriteStartObject()
    {
        _currentDepth++;
        UpdateIndentSetting();
        base.WriteStartObject();
    }

    public override void WriteEndObject()
    {
        base.WriteEndObject();
        _currentDepth--;
        UpdateIndentSetting();
    }

    public override void WriteStartArray()
    {
        _currentDepth++;
        UpdateIndentSetting();
        base.WriteStartArray();
    }

    public override void WriteEndArray()
    {
        base.WriteEndArray();
        _currentDepth--;
        UpdateIndentSetting();
    }

    private void UpdateIndentSetting()
    {
        // 当前深度未超过限制时保留缩进,超过则切换为紧凑格式
        var shouldIndent = _currentDepth <= _maxIndentDepth && _originalOptions.Indented;
        Options = _originalOptions with { Indented = shouldIndent };
    }
}

2. 封装序列化工具方法

public static class JsonSerializerHelper
{
    public static string SerializeWithLimitedIndent<T>(T value, int maxIndentDepth, JsonSerializerOptions? options = null)
    {
        options ??= new JsonSerializerOptions();
        var originalIndented = options.Indented;
        options.Indented = true; // 确保基础缩进开启,后续由自定义Writer控制

        using var stream = new MemoryStream();
        using var writer = new LimitedIndentJsonWriter(
            stream,
            new JsonWriterOptions
            {
                Indented = options.Indented,
                Encoder = options.Encoder,
                SkipValidation = options.SkipValidation,
                MaxDepth = options.MaxDepth
            },
            maxIndentDepth
        );
        
        JsonSerializer.Serialize(writer, value, options);
        writer.Flush();
        stream.Position = 0;
        
        return Encoding.UTF8.GetString(stream.ToArray());
    }
}

3. 使用示例

// 生成两层深度缩进的结果(对应输出2)
var result2 = JsonSerializerHelper.SerializeWithLimitedIndent(items, 2);
Console.WriteLine(result2);

// 生成三层深度缩进的结果(对应输出3)
var result3 = JsonSerializerHelper.SerializeWithLimitedIndent(items, 3);
Console.WriteLine(result3);

关键说明

  • 自定义Writer通过_currentDepth跟踪序列化层级,进入对象/数组时深度+1,退出时-1
  • 超过_maxIndentDepth后自动关闭缩进,该层级及以下的内容会被压缩到一行
  • 保留了原始JsonSerializerOptions的所有配置,仅动态修改缩进状态

内容的提问来源于Stack Exchange,提问作者Frank Schwieterman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:07:01