JSON Formatter
Format, beautify, and validate JSON with configurable indentation, optional key sorting, and instant error feedback.
What this JSON formatter online does
Paste raw, minified, or messy JSON into the input editor and press Format (or Ctrl+Enter) to format JSON into clean, indented output — with key sorting and configurable indent size. The same click is how you validate JSON: if parsing fails, you get the exact line and column of the error instead of a blob of unreadable text.
Why this exists: every .NET developer working with REST APIs has pasted a minified response from HttpClient into a text editor and tried to read it. System.Text.Json's default serializer output is compact and fast — exactly what you want in production, and completely unreadable when you're debugging a 400 response at 11pm. This formatter exists because I got tired of that specific problem. I kept switching to browser DevTools just to pretty-print a string I already had in my IDE.
Once your JSON is formatted and confirmed valid, a common next step in a .NET project is turning that payload into a matching type: the JSON to C# Class/Record Generator takes the exact same JSON and generates ready-to-use C# classes or records, with nullable reference types and System.Text.Json or Newtonsoft.Json attribute options. Need to go the other way — from an existing C# class to a sample JSON payload for a test or a mock response? See the C# to JSON Sample Generator.
A field note: more than once I've burned twenty minutes chasing a "missing" field in an API response, only to find it was there all along — nested one level deeper than I expected, or spelled with different casing than the DTO. Formatting the raw payload and reading the actual structure, instead of trusting my mental model of it, is usually the fastest way out of that hole. It's a small, unglamorous class of bug, but it eats a disproportionate amount of debugging time precisely because the fix is one glance at correctly indented JSON.
How to format JSON online
- Paste your raw, minified, or partially formatted JSON into the input editor on the left.
- Press Ctrl+Enter or click Format.
- Choose indent size and enable Sort keys to alphabetise all object keys recursively — useful before comparing two objects side by side.
- Use the Copy button to grab the formatted output.
Anatomy of a JSON object
Every JSON object breaks down into the same handful of parts, no matter how deeply nested the document gets:
JSON in .NET: System.Text.Json vs Newtonsoft.Json
Two libraries dominate JSON handling in .NET. System.Text.Json (built in since .NET Core 3.0) is the default for ASP.NET Core responses, HttpClient, and EF Core. Newtonsoft.Json (Json.NET) is the older library still present in most enterprise codebases. They differ in ways that cause real bugs:
System.Text.Jsonis case-sensitive by default —userIdandUserIdare different keys unless you configurePropertyNameCaseInsensitive = trueinJsonSerializerOptions.- Newtonsoft handles missing properties gracefully by default;
System.Text.Jsonrequires[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]or global options to control null and unknown property behaviour. - Newtonsoft serializes
enumvalues as their integer form by default;System.Text.Jsondoes the same, but theJsonStringEnumConvertermust be registered explicitly to get string values in JSON output.
When deserialization silently returns null for a field you know the API returns, format the raw JSON here first. The mismatch between what arrived and what your DTO expects is almost always visible immediately in the formatted output.
// Format an HttpClient response for debug output (System.Text.Json)
var raw = await httpClient.GetStringAsync("https://api.example.com/orders/42");
// Round-trip through JsonElement to get indented output
var formatted = JsonSerializer.Serialize(
JsonSerializer.Deserialize<JsonElement>(raw),
new JsonSerializerOptions { WriteIndented = true }
);
Debug.WriteLine(formatted);
// Lower-allocation alternative: JsonDocument + Utf8JsonWriter
using var doc = JsonDocument.Parse(raw);
using var ms = new MemoryStream();
using var w = new Utf8JsonWriter(ms, new JsonWriterOptions { Indented = true });
doc.WriteTo(w);
w.Flush();
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
This tool uses the JsonDocument path internally — it's what runs when you press Format or Ctrl+Enter. The formatter also accepts trailing commas and // comments via JsonDocumentOptions.AllowTrailingCommas and CommentHandling.Skip, so appsettings.json and JSONC config files paste in cleanly.
Five real .NET debugging scenarios
- A 422 Unprocessable Entity from your ASP.NET Core controller where model binding silently fails. Format the raw request body to see exactly which field name or casing doesn't match your DTO — the discrepancy is always visible once the JSON is readable.
- Comparing two
appsettings.jsonfiles across environments. Enable Sort keys on both, then diff them. Unsorted keys make environment diffs noisy; sorted output makes additions, removals, and value changes obvious. - Reading a dead-lettered Azure Service Bus message. Service Bus stores message bodies as UTF-8 text. Format the body to understand the payload structure before fixing the consumer handler.
- Inspecting a Stripe or GitHub webhook payload during local development. Paste the raw body captured by your tunnel (ngrok or Cloudflare Tunnel) to understand the event schema before writing the
[FromBody]DTO and handler. - Verifying a custom
JsonConverter<T>is serializing correctly. Serialize a test object with your converter registered and paste the output here. Any field that's missing, renamed, or wrong type is immediately visible in the formatted view.
Common JSON validation errors
| Error | Cause | Fix |
|---|---|---|
| Unexpected token | Single quotes used as string delimiters | Replace ' with " |
| Trailing comma | Comma after the last element (illegal in strict JSON) | This tool strips trailing commas automatically |
| Unexpected end of input | Missing closing } or ] | Check every opening bracket has a matching close |
| Duplicate key | Same key appears twice in one object | RFC 8259 leaves this undefined — JsonDocument preserves both |
| Invalid escape sequence | Backslash not followed by a valid escape char | Use \\ for a literal backslash in a string value |
JSON value types (RFC 8259 §3)
- Object — unordered set of key/value pairs in
{ }. Keys must be double-quoted strings. - Array — ordered list of values in
[ ], separated by commas. - String — Unicode characters in double quotes. Escape sequences:
\"\\\n\r\t\uXXXX. - Number — integer or floating-point, no quotes, no hex or octal.
- Boolean —
trueorfalse(lowercase only). - Null —
null(lowercase only).
Frequently asked questions
Why does System.Text.Json produce different output than Newtonsoft for the same C# object? The default property naming policy differs: ASP.NET Core registers JsonNamingPolicy.CamelCase globally, so MyProperty serializes as myProperty. Newtonsoft preserves the C# property casing by default. Additionally, DateTime, enum, and null values are handled differently by each library's built-in converters.
Why does my ASP.NET Core controller return camelCase JSON when my DTO uses PascalCase? builder.Services.AddControllers() registers JsonNamingPolicy.CamelCase as the default. To preserve C# property casing globally, add .AddJsonOptions(o => o.JsonSerializerOptions.PropertyNamingPolicy = null) in Program.cs.
How do I get readable JSON from EF Core's ToJson() document columns? Read the raw string from EF, parse it with JsonDocument.Parse(), and write it with Indented = true. Pasting the result here lets you verify the structure before writing the entity type configuration.
Why does deserializing JSON into a C# record fail with a "no suitable constructor" error? System.Text.Json matches JSON properties to a record's positional constructor parameters by name (case-insensitively by default). If the JSON has an extra or missing property, or a property name that doesn't line up with a parameter name, deserialization throws instead of guessing. Format the JSON here first to check its actual property names against the record definition before debugging the exception further.
How do I map a JSON property name that isn't a valid C# identifier, like "first-name"? Decorate the corresponding C# property or record parameter with [JsonPropertyName("first-name")]. Without it, System.Text.Json looks for a property literally named first-name and silently leaves the C# property at its default value when it doesn't find one — no exception, which is what makes this bug easy to miss.
Native code equivalents
Production-ready snippets — same logic the tool runs, in your languageusing System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
// Pretty-print JSON with System.Text.Json — built-in, no NuGet required (.NET 5+)
static string FormatJson(string raw, bool sortKeys = false)
{
if (sortKeys)
{
var node = JsonNode.Parse(raw)!;
var opts = new JsonSerializerOptions { WriteIndented = true };
return JsonSerializer.Serialize(SortNode(node), opts);
}
using var doc = JsonDocument.Parse(raw);
using var ms = new MemoryStream();
using var writer = new Utf8JsonWriter(ms, new JsonWriterOptions { Indented = true });
doc.WriteTo(writer);
writer.Flush();
return Encoding.UTF8.GetString(ms.ToArray());
}
// Minify — strip all whitespace
static string MinifyJson(string raw)
{
using var doc = JsonDocument.Parse(raw);
return JsonSerializer.Serialize(doc.RootElement);
}
// Recursively sort object keys alphabetically
static JsonNode SortNode(JsonNode node)
{
if (node is JsonObject obj)
{
var sorted = new JsonObject();
foreach (var (k, v) in obj.OrderBy(p => p.Key))
sorted[k] = v is null ? null : SortNode(v.DeepClone());
return sorted;
}
if (node is JsonArray arr)
{
var result = new JsonArray();
foreach (var item in arr)
result.Add(item is null ? null : SortNode(item.DeepClone()));
return result;
}
return node.DeepClone();
}
// Example
string pretty = FormatJson("{\"b\":2,\"a\":1}", sortKeys: true);
string minified = MinifyJson(pretty);
Console.WriteLine(pretty);
// {
// "a": 1,
// "b": 2
// }
Console.WriteLine(minified); // {"a":1,"b":2}JSON input
{
"name": "DevToolsHub",
"stack": ["Blazor", ".NET 8"]
}Formatted output
JSON result