Repository navigation
Development
For anyone changing the library. AGENTS.md at the repository root holds the rules in full; this page is the tour.
| Path | What it holds |
|---|---|
JsonPrettyPrinterPlus/ |
The library. JsonPrettyPrinter.cs has the extension methods and the public printer, PrettyPrintEngine.cs the internal formatter (one switch per character), JsonPrettyPrintOptions.cs the options record, JsonSerialization/JsonExtensions.cs the System.Text.Json helpers, and IsExternalInit.cs the one polyfill (it lets netstandard2.0 compile init setters). |
tests/Golden/ |
The golden recordings of the published 3.0.1 (1,174 cases per runtime), the program that made them, the public API list, and the 1.0.1.1 and 2.1.1 recordings under upgrade/. Never edited. |
tests/JsonPrettyPrinterPlus.GoldenTests/ |
Replays every recorded case against the library on net10.0 and net48 (64-bit) and checks every public API line. |
tests/consumers/, tests/package/
|
Fresh consumer projects of the packed or published package, and the package content check. |
JsonPrettyPrinterPlusTests/ |
37 NUnit 4 tests, run on net10.0 and net48. The net48 leg executes the netstandard2.0 build of the library. TestFiles/jsonLintBeautifyExample.json is the reference output for the nested-object test. |
benchmarks/JsonPrettyPrinterPlus.Benchmarks/ |
A BenchmarkDotNet project that pretty prints a generated 1 MB document. Not packed; its results folder is ignored by Git, and the numbers live in the changelog. |
.github/workflows/ |
ci.yml builds, tests and checks the package; release.yml publishes; verify-published.yml checks a release from nuget.org. dependabot.yml proposes NuGet, SDK and action updates weekly after a seven-day cooldown. |
ai-docs/ |
Plans, decisions, notes and the log from past work, for people and agents alike; INDEX.md lists them. |
global.json |
Pins the SDK to 10.0.401 with rollForward: latestFeature. |
The library is one assembly, JsonPrettyPrinterPlus.dll, 12.8 KB per target framework.
dotnet restore --locked-mode
dotnet format --verify-no-changes
dotnet build -c Release
dotnet test -c Release
dotnet pack JsonPrettyPrinterPlus -c Release -o artifacts
dotnet run -c Release --project benchmarks/JsonPrettyPrinterPlus.Benchmarks
Lock files are committed for every project. After changing a package reference, run plain dotnet restore and commit the updated packages.lock.json. .editorconfig is enforced both by the format check and in the build (EnforceCodeStyleInBuild), warnings are errors, and the analyzers run at latest-recommended. Files are LF; .gitattributes says so, and the format check on the Windows runner depends on it.
The net48 tests execute only on Windows. On Linux and macOS, dotnet test builds the net48 leg (the reference assemblies package makes that possible) and runs the net10.0 one.
Output for well-formed input is the contract. The suite covers the original four round-trip tests from 2014 and every bug fixed in 2.1.0: escapes, empty scopes at any depth, null input, stray and mismatched brackets, and state left behind by malformed input. It also pins idempotence, a JsonNode.DeepEquals round trip, each option, each overload and the serializer helpers. Behind it, the golden replay checks all 1,174 answers the published 3.0.1 gives on each runtime; its recordings are never edited, and CI fails if they change. A change to what PrettyPrintJson() writes needs a test and a changelog entry. A change that only affects broken input is at most a minor version.
The library multi-targets netstandard2.0 and net10.0. Nothing from .NET 5 or later goes in without an #if or a polyfill: no ArgumentNullException.ThrowIfNull, no HashCode. The net10.0 build is trimmable and AOT compatible, so any member that touches reflection-based System.Text.Json carries RequiresUnreferencedCode and RequiresDynamicCode under #if NET5_0_OR_GREATER and gets a JsonTypeInfo<T> overload beside it.
dotnet run -c Release --project benchmarks/JsonPrettyPrinterPlus.Benchmarks pretty prints a deterministic 1 MB minified document with nested objects, arrays, escapes and numbers, ten iterations after three warm-ups, with the memory diagnoser on. Put before and after numbers in CHANGELOG.md when a change touches the engine. Performance and threading has the history.
ci.yml runs on every push to master and every pull request, on Ubuntu and Windows: the golden files are unchanged, locked restore, format check, build, a NuGet audit that fails on any advisory, the net10.0 tests (and on Windows the net48 tests), a pack with package validation against the last release, a check of the package's files and dependencies, and fresh consumer projects of the packed package. A final job named ci is the check the master branch requires. Actions are pinned to commit SHAs.
Nothing reaches nuget.org without the maintainer. release.yml runs for a v* tag, which only repository admins can push. It checks that the tag equals <Version>, sits on master and has a green ci check, builds and tests on Linux and Windows, checks the package it will push and runs the consumers on it, and attests it. Then it waits for approval on the nuget environment, signs in to nuget.org with Trusted Publishing (GitHub OIDC exchanged for a one-hour key, no stored API key), pushes, and creates a GitHub Release with the changelog section and the packages.
- Add the section to
CHANGELOG.md, with its date, and set<Version>inJsonPrettyPrinterPlus/JsonPrettyPrinterPlus.csproj. - Merge through a pull request and wait for
cito be green onmaster. - Tag the commit
v<version>and push the tag. Tag only after green: tags are not force-pushed here, so a tag on a failing commit burns the number. That is how 2.1.0 and 3.0.0 became 2.1.1 and 3.0.1. - Approve the deployment in the Actions run, then run
verify-published.ymlwith the version: it waits for both nuget.org indexes, checks the repository signature and runs the consumers from nuget.org on Linux, macOS and Windows. - Set
PackageValidationBaselineVersionin the project file to the released version, so the next pack is checked against it.
From AGENTS.md:
- Output for well-formed input is the contract.
- No net5+ APIs without an
#if. - Trim and AOT annotations on anything reflective.
- LF line endings.
- The tag equals the version.
- The golden recordings are never edited.
- Write what was learned to
ai-docs/before finishing. - No AI attribution in commits, pull requests or files.
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.
Using it
- Getting started
- API reference
- Output format
- Not a validator
- Serialisation helpers
- Recipes
- Performance and threading
- FAQ
The releases
Contributing
Elsewhere