There is no method to control the formatting of specific nested tokens inside a JToken
hierarchy when writing to JSON. Thus we will need to roll our own:
public static partial class JsonExtensions
{
public static string ToFormattedString(this JToken token, params JsonConverter[] converters)
{
if (token == null)
throw new ArgumentNullException();
using (var sw = new StringWriter(CultureInfo.InvariantCulture))
{
using (var jw = new JsonTextWriter(sw) { Formatting = Formatting.Indented })
FormattedWriteTo(token, jw, 0, converters);
return sw.ToString();
}
}
static void FormattedWriteTo(JToken token, JsonTextWriter writer, int depth, params JsonConverter[] converters)
{
if (token == null)
{
writer.WriteNull();
}
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);
writer.WriteEndObject();
}
else if (token is JArray array)
{
// Disable formatting for arrays.
// You could smarten this up further by e.g. checking to see whether the array contents are all primitive JValue tokens.
var old = writer.Formatting;
// The question requires an extra space between the property name and the array value.
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);
writer.WriteEndArray();
writer.Formatting = old;
}
else if (token is JProperty property)
{
writer.WritePropertyName(property.Name);
FormattedWriteTo(property.Value, writer, depth+1, converters);
}
else
{
// JValue, JRaw, JConstructor
token.WriteTo(writer);
}
}
}
Then JToken.FromObject(myObj).ToFormattedString()
produces, as required:
{
"Vector": [1,2,3,4,5]
}
Notes:
Demo fiddle here.