using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Collections.ObjectModel;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public static partial class JsonExtensions
public static string ToFormattedString(this JToken token, params JsonConverter[] converters)
throw new ArgumentNullException();
using (var sw = new StringWriter(CultureInfo.InvariantCulture))
using (var jw = new JsonTextWriter(sw) { Formatting = Formatting.Indented })
FormattedWriteTo(token, jw, 0, converters);
static void FormattedWriteTo(JToken token, JsonTextWriter writer, int depth, params JsonConverter[] converters)
else if (token is JObject obj)
IList<JToken> asList = obj;
writer.WriteStartObject();
for (int i = 0, n = asList.Count; i < n; i++)
FormattedWriteTo(asList[i], writer, depth+1, converters);
else if (token is JArray array)
var old = writer.Formatting;
if (depth > 0 && old == Formatting.Indented)
writer.WriteWhitespace(" ");
writer.Formatting = Formatting.None;
writer.WriteStartArray();
for (int i = 0, n = array.Count; i < n; i++)
FormattedWriteTo(array[i], writer, depth+1, converters);
else if (token is JProperty property)
writer.WritePropertyName(property.Name);
FormattedWriteTo(property.Value, writer, depth+1, converters);
public static void Test()
Console.WriteLine(JToken.FromObject(myObj).ToFormattedString());
Assert.IsTrue(JToken.FromObject(myObj).ToFormattedString() == GetRequiredJson());
Dates = new [] { new [] { new DateTime(2020, 12, 16) }, new [] { new DateTime(2020, 12, 17) }},
Console.WriteLine(JToken.FromObject(myObj2).ToFormattedString());
static string GetRequiredJson() => @"{
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("{0} version: {1}", typeof(JsonSerializer).Assembly.GetName().Name, typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.Location.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];