Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
436 views
in Technique[技术] by (71.8m points)

c# - How do you limit indentation depth when serializing with Newtonsoft.Json

When serializing an object using Newtonsoft.Json, is there a way to stop indentation of the serialized values after a given depth?

For example given the object in Listing 1, is there a way to subclass the JsonConverter or JsonWriter to indent only up to a certain level so that instead of the output in Dump 1, you get that in Dump 2 or Dump 3?

Listing 1

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

Dump 1: Fully Indented

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

Dump 2: Two levels deep

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

Dump 3: Three levels deep

[
  {
    "Name": "John",
    "Age": 5,
    "Address": {
      "Home": "No. 123, Oak Street",
      "Email": "[email protected]"
    },
    "Extra": {
      "Serials": [ 20, 30, 40, 50 ]
    }
  },
  {
    "Name": "Jean",
    "Age": 2,
    "Address": {
      "Home": "No. 321, Cliff Road",
      "Email": "[email protected]"
    },
    "Extra": {
      "Serials": [ 25, 35, 45, 55 ]
    }
  }
]
question from:https://stackoverflow.com/questions/65557528/how-do-you-limit-indentation-depth-when-serializing-with-newtonsoft-json

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yes, you can cap the indentation depth by subclassing the JsonTextWriter like this:

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;
    }
}

You can create a helper method to make it easy to use the writer:

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();
    }
}

Then you can do:

string json = SerializeWithCustomIndenting(yourObject, 2);  // indent to 2 levels max

Here is a working demo: https://dotnetfiddle.net/XhwsGF


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...