Skip to content

Instantly share code, notes, and snippets.

@thoemmi
Created June 13, 2022 20:44
Show Gist options
  • Save thoemmi/150ae4622ea651f6856b92703b8e0f7a to your computer and use it in GitHub Desktop.
Save thoemmi/150ae4622ea651f6856b92703b8e0f7a to your computer and use it in GitHub Desktop.
Extension method for Spectre.Console to write JSON with syntax highlighting
public static class AnsiConsoleExtensions
{
public static IAnsiConsole WriteJson(this IAnsiConsole console, JsonElement node, JsonStyle? jsonStyle = null)
{
ArgumentNullException.ThrowIfNull(console);
ArgumentNullException.ThrowIfNull(node);
console.WriteJson(node, jsonStyle ?? JsonStyle.Default, 0);
return console;
}
private static IAnsiConsole WriteJson(this IAnsiConsole console, JsonElement node, JsonStyle jsonStyle, int indentionLevel)
{
switch (node.ValueKind)
{
case JsonValueKind.Undefined:
break;
case JsonValueKind.Object:
var indent = new string(' ', indentionLevel * jsonStyle.IndentSize);
var firstPropertyWritten = false;
foreach (var property in node.EnumerateObject())
{
if (!firstPropertyWritten)
{
console.Write(new Text("{", jsonStyle.CurlyBracketStyle));
console.WriteLine();
}
else
{
console.Write(new Text(",", jsonStyle.ValueSeparatorStyle));
console.WriteLine();
}
console.Write(indent + " \"");
console.Write(new Text(property.Name, jsonStyle.NameStyle));
console.Write("\"");
console.Write(new Text(": ", jsonStyle.NameSeparatorStyle));
console.WriteJson(property.Value, jsonStyle, indentionLevel + 1);
firstPropertyWritten = true;
}
if (firstPropertyWritten)
{
console.WriteLine();
console.Write(indent);
console.Write(new Text("}", jsonStyle.CurlyBracketStyle));
}
else
{
console.Write(new Text("{}", jsonStyle.CurlyBracketStyle));
}
break;
case JsonValueKind.Array:
var indentArray = new string(' ', (indentionLevel + 1) * jsonStyle.IndentSize);
var firstPropertyWritten2 = false;
foreach (var child in node.EnumerateArray())
{
if (!firstPropertyWritten2)
{
console.Write(new Text("[", jsonStyle.SquareBracketStyle));
console.WriteLine();
}
else
{
console.Write(new Text(",", jsonStyle.ValueSeparatorStyle));
console.WriteLine();
}
console.Write(indentArray);
console.WriteJson(child, jsonStyle, indentionLevel + 1);
firstPropertyWritten2 = true;
}
if (firstPropertyWritten2)
{
console.WriteLine();
console.Write(indentArray[..^2]);
console.Write(new Text("]", jsonStyle.SquareBracketStyle));
}
else
{
console.Write(new Text("[]", jsonStyle.SquareBracketStyle));
}
break;
case JsonValueKind.String:
console.Write(new Text("\"" + node.GetString() + "\"", jsonStyle.StringStyle));
break;
case JsonValueKind.Number:
console.Write(new Text(node.GetRawText(), jsonStyle.NumberStyle));
break;
case JsonValueKind.True:
console.Write(new Text("true", jsonStyle.BooleanStyle));
break;
case JsonValueKind.False:
console.Write(new Text("false", jsonStyle.BooleanStyle));
break;
case JsonValueKind.Null:
console.Write(new Text("null", jsonStyle.NullStyle));
break;
default:
throw new ArgumentOutOfRangeException();
}
if (indentionLevel == 0)
console.WriteLine();
return console;
}
}
public record JsonStyle
{
public static readonly JsonStyle Default = new();
public int IndentSize { get; init; } = 2;
public Style NameStyle { get; init; } = new (Color.LightSkyBlue1);
public Style StringStyle { get; init; } = new (Color.LightPink3);
public Style NumberStyle { get; init; } = new (Color.DarkSeaGreen2);
public Style NullStyle { get; init; } = new (Color.SkyBlue3);
public Style BooleanStyle { get; init; } = new (Color.SkyBlue3);
public Style CurlyBracketStyle { get; init; } = new (Color.Grey82);
public Style SquareBracketStyle { get; init; } = new (Color.Grey82);
public Style NameSeparatorStyle { get; init; } = new (Color.Grey82);
public Style ValueSeparatorStyle { get; init; } = new (Color.Grey82);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment