Repository navigation
Versions and Upgrading
Dates are the changelog's. Full notes: CHANGELOG.md.
| Version | Date | Targets | What changed |
|---|---|---|---|
| 3.0.2 | 2026-09-29 | netstandard2.0, net10.0 | The current release. No library change: every answer 3.0.1 gives is recorded (1,174 cases on .NET Framework 4.8 and on .NET 10) and checked on every build. The README inside the package is corrected (comments, numbers on .NET Framework, an upgrade section), and releases go through a gated workflow with a build provenance attestation. 3.0.2-beta.1 (2026-09-28) rehearsed it. |
| 3.0.1 | 2026-09-25 | netstandard2.0, net10.0 | Breaking: lines end with \n on every OS instead of Environment.NewLine; the strategy classes, JsonPPStrategyContext, PPScopeState and the fields SpacesPerIndent and IsProcessingVariableAssignment are gone from the public API; ToJSON() is removed (use ToJson()); JsonPrettyPrinter is sealed. Inside, one engine with a switch per character replaces the strategy objects: the 1 MB benchmark went from 11.1 ms to 4.5 ms. Output for well-formed input is otherwise the same as 2.1.1. |
| 3.0.0 | 2026-09-25 | Tagged but never published: its publish job failed on a workflow mistake. Same code as 3.0.1. | |
| 2.1.1 | 2026-09-25 | netstandard2.0, net10.0 | Fixes: an escaped backslash before a closing quote ("x\\") no longer swallows the rest of the document; {} and [] print on one line at any depth; null input throws ArgumentNullException; a stray or mismatched closing bracket throws FormatException with the index; a reused printer starts clean after malformed input. Added: JsonPrettyPrintOptions (IndentSize, UseTabs, NewLine), the TextWriter and ReadOnlySpan<char> overloads, ToJson(), the JsonSerializerOptions and JsonTypeInfo<T> overloads, XML documentation, nullable annotations, trimming and AOT support on net10.0, the icon, the benchmark project. Binary compatible with 2.0.0; the old strategy types stayed public but hidden from IntelliSense. |
| 2.1.0 | 2026-09-25 | Tagged but never published: the Windows CI leg failed on a lock file difference. Same code as 2.1.1. | |
| 2.0.0 | 2026-09-24 | netstandard2.0, net10.0 | Rebuilt with the current SDK after twelve years; net35 dropped. ToJSON() and DeserializeFromJson() moved from JavaScriptSerializer to System.Text.Json. SourceLink, deterministic build, symbols package, the README inside the package. |
| 1.0.1.1 | 2014-04-03 | net35 | The 2014 release, and the one behind 200,000 of the package's 310,000 downloads. |
| 1.0.1, 1.0.0 | 2014-03-31 | net35 | The first releases. |
Every version stays listed on nuget.org. Nothing before 3.0.2 receives fixes.
PrettyPrintJson() is the same call in the same namespace, so most code compiles unchanged. Check these points.
1.0.1.1 shipped net35. 3.x ships netstandard2.0 and net10.0, so a project needs .NET Framework 4.6.2 or later, .NET Core 2.0 or later, or .NET 5 or later. A project stuck on .NET Framework 3.5, 4.0 or 4.5 cannot take it.
For well-formed JSON the layout is the same: four spaces per level, one value per line, a space after each colon. Three things differ.
- Lines end with a line feed on every OS. 1.x wrote
Environment.NewLine, which is CRLF on Windows. Passnew JsonPrettyPrintOptions { NewLine = Environment.NewLine }to get that back, or compare with the line endings normalised. - Empty objects and arrays print as
{}and[]on one line. 1.x put the closing bracket on its own line. - A string ending in an escaped backslash (
"x\\") is now read correctly. 1.x took the\"as an escaped quote and copied the rest of the document through unformatted.
Two error cases changed type: null input throws ArgumentNullException (was NullReferenceException) and a closing bracket with nothing to close throws FormatException (was InvalidOperationException from a stack). A catch (Exception) still catches both.
new JsonPrettyPrinter(new JsonPPStrategyContext()) is now new JsonPrettyPrinter(), or new JsonPrettyPrinter(options). The JsonPrettyPrinterInternals namespace and everything in it is gone. SpacesPerIndent became JsonPrettyPrintOptions.IndentSize.
ToJSON() is now ToJson(), and both it and DeserializeFromJson<T>() run on System.Text.Json instead of JavaScriptSerializer. The JSON they produce differs.
JavaScriptSerializer (1.x) |
System.Text.Json (2.0 and later) | |
|---|---|---|
DateTime |
\/Date(1262325600000)\/ |
2010-01-01T00:00:00 (ISO 8601, no time zone suffix for an unspecified kind) |
| A quote in a string | \" |
\u0022 |
An apostrophe, <, >, &
|
as is |
\u0027, \u003C, \u003E, \u0026
|
| Non-ASCII characters | as is |
\u00E9 and so on |
| Property names | as declared | as declared |
DeserializeFromJson<object>() |
Dictionary<string, object> |
JsonElement |
| Property name matching | case-insensitive | case-sensitive unless PropertyNameCaseInsensitive is set |
To keep quotes and non-ASCII text readable, pass serializer options with Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping; Serialisation helpers shows the call. The escapes are valid JSON and every parser reads them; they only look different. If you need JavaScriptSerializer itself, stay on 1.0.1.1 or serialise with it yourself and call PrettyPrintJson() on the result.
The golden capture that guards 3.x was run against 1.0.1.1 too, with every case its API allows: 446 of them, on .NET Framework 4.8 and on .NET 10 (the recordings and the comparison reports are in the repository under tests/Golden/upgrade/). On .NET Framework 273 answers are identical, 60 differ only in line endings and 110 differ. 1.0.0 and 1.0.1 give the same answers as 1.0.1.1 there. Besides the points above, the recordings show these.
- A closing bracket of the wrong kind (
[1}) now throwsFormatException; 1.x printed it. - Unclosed documents and trailing commas no longer leave a line of indentation only.
- A 1.x printer object reused after an unterminated string printed the next document unformatted, and after an unclosed one it indented the next from the old depth. 3.x starts every document clean.
-
ToJSON()wrote public fields;ToJson()writes properties only.TimeSpanandVersionbecame strings instead of objects, byte arrays base64 instead of number arrays, and aDictionary<int, T>now serialises instead of throwing. -
ToJSON()wroteNaNandInfinity, which are not valid JSON;ToJson()throwsArgumentExceptionfor them. A lone surrogate becomes U+FFFD, and a reference cycle throwsJsonException. - 1.x read dates in the machine's time zone:
"2010-01-01T00:00:00Z"came back as a localDateTime, and aDateTimeof unspecified kind was written as local time. 3.x keeps the kind. -
DeserializeFromJson()in 1.x accepted single quotes, unquoted property names, numbers written as strings, strings written as numbers,1e3for an integer and enum names. 3.x throwsJsonExceptionfor each, and a lower-case property name no longer fills the property (without an error). The/Date(...)/strings 1.x wrote cannot be read back. - On .NET Core and .NET 5 or later, 1.x's
ToJSON()andDeserializeFromJson()never worked: every call throwsFileNotFoundExceptionfor System.Web.Extensions. Its printer works there.
3.x ships XML documentation for IntelliSense, a symbols package, SourceLink and the README inside the package. On netstandard2.0 it depends on System.Text.Json and System.Memory; the net10.0 build has no dependencies.
2.0.0 users get everything in the 2.1.1 row above. The breaking changes of 3.0 are these.
- Output lines end with
\n. PassNewLine = Environment.NewLineif something compared against CRLF. -
ToJSON()is gone;ToJson()has the same overloads and more. - The
JsonPrettyPrinterInternalsnamespace is gone:JsonPPStrategyContext,PPScopeState,ICharacterStrategy, the ten strategy classes, theJsonPrettyPrinter(JsonPPStrategyContext)constructor and the fieldsIsProcessingVariableAssignmentandSpacesPerIndent. Usenew JsonPrettyPrinter()andJsonPrettyPrintOptions. If you had written a strategy of your own, open an issue describing what it did. -
JsonPrettyPrinteris sealed.
The same list as above, minus the fixes and additions that 2.1.1 already had. Measured with the same cases, 2.1.1 and 3.0.1 differ only in line endings, apart from IndentSize = int.MaxValue, which now fails with OutOfMemoryException in the constructor instead of at the first call. 2.1.1 shows the removed types with [EditorBrowsable(Never)], so code that compiles against 2.1.1 without touching hidden members compiles against 3.x once ToJSON is renamed.
v2.1.0 and v3.0.0 exist in the repository but never reached nuget.org. Each tag was pushed to a commit whose CI run failed. Tags are not moved here, so the fixed commits were released as 2.1.1 and 3.0.1. The changelog keeps both entries so the version history reads correctly.
This wiki describes JsonPrettyPrinter 3.0.2 and was last updated on 2026-09-30. The library is MIT licensed. Report problems in the issues. On NuGet: JsonPrettyPrinter.
Using it
- Getting started
- API reference
- Output format
- Not a validator
- Serialisation helpers
- Recipes
- Performance and threading
- FAQ
The releases
Contributing
Elsewhere