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

Ale*_*fie 1 .net c# json json.net

使用 Newtonsoft.Json 序列化对象时,有没有办法在给定深度后停止序列化值的缩进?

例如,给定清单 1中的对象,是否有办法对JsonConverter或进行子类化JsonWriter,仅缩进到一定级别,以便在Dump 2或Dump 3中获得输出,而不是 Dump 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 } }
    }
};
Run Code Online (Sandbox Code Playgroud)

转储 1:完全缩进

[
  {
    “姓名”:“约翰”,
    “年龄”:5,
    “地址”: {
      “家”:“橡树街123号”,
      “电子邮件”:“john@mail.com”
    },
    “额外的”: {
      “连续剧”:[
        20、
        30、
        40、
        50
      ]
    }
  },
  {
    “姓名”:“吉恩”,
    “年龄”:2,
    “地址”: {
      “家”:“悬崖路321号”,
      “电子邮件”:“jean@mail.com”
    },
    “额外的”: {
      “连续剧”:[
        25、
        35、
        45、
        55
      ]
    }
  }
]

转储 2:两层深

[
  {
    “姓名”:“约翰”,
    “年龄”:5,
    "地址": { "家庭": "橡树街123号", "邮箱": "john@mail.com" },
    "额外": { "连续剧": [ 20, 30, 40, 50 ] }
  },
  {
    “姓名”:“吉恩”,
    “年龄”:2,
    "地址": { "家庭": "崖道321号", "电子邮箱": "jean@mail.com" },
    "额外": { "连续剧": [ 25, 35, 45, 55 ] }
  }
]

转储 3:三层深

[
  {
    “姓名”:“约翰”,
    “年龄”:5,
    “地址”: {
      “家”:“橡树街123号”,
      “电子邮件”:“john@mail.com”
    },
    “额外的”: {
      “连续剧”:[ 20, 30, 40, 50 ]
    }
  },
  {
    “姓名”:“吉恩”,
    “年龄”:2,
    “地址”: {
      “家”:“悬崖路321号”,
      “电子邮件”:“jean@mail.com”
    },
    “额外的”: {
      “连续剧”:[ 25, 35, 45, 55 ]
    }
  }
]

Bri*_*ers 6

是的,您可以通过子类化来限制缩进深度,JsonTextWriter如下所示:

public class CustomIndentingJsonTextWriter : JsonTextWriter
{
    public int? MaxIndentDepth { get; set; } 

    public CustomIndentingJsonTextWriter(TextWriter writer) : base(writer)
    {
        Formatting = Formatting.Indented;
    }

    public override void WriteStartArray()
    {
        base.WriteStartArray();
        if (MaxIndentDepth.HasValue && Top > MaxIndentDepth.Value) 
            Formatting = Formatting.None;
    }

    public override void WriteStartObject()
    {
        base.WriteStartObject();
        if (MaxIndentDepth.HasValue && Top > MaxIndentDepth.Value) 
            Formatting = Formatting.None;
    }

    public override void WriteEndArray()
    {
        base.WriteEndArray();
        if (MaxIndentDepth.HasValue && Top <= MaxIndentDepth.Value) 
            Formatting = Formatting.Indented;
    }

    public override void WriteEndObject()
    {
        base.WriteEndObject();
        if (MaxIndentDepth.HasValue && Top <= MaxIndentDepth.Value) 
            Formatting = Formatting.Indented;
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以创建一个辅助方法以方便使用编写器:

public static string SerializeWithCustomIndenting(object obj, int? maxIdentDepth = null)
{
    using (StringWriter sw = new StringWriter())
    using (CustomIndentingJsonTextWriter jw = new CustomIndentingJsonTextWriter(sw))
    {
        jw.MaxIndentDepth = maxIdentDepth;
        JsonSerializer ser = new JsonSerializer();
        ser.Serialize(jw, obj);
        return sw.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

string json = SerializeWithCustomIndenting(yourObject, 2);  // indent to 2 levels max
Run Code Online (Sandbox Code Playgroud)

这是一个工作演示: https: //dotnetfiddle.net/XhwsGF