Reputation: 12613
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 ] } } ]
Upvotes: 1
Views: 1021
Reputation: 129797
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
Upvotes: 6