jrp

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2026 License: MIT Imports: 8 Imported by: 0

README

json-really-pretty-go

A Go package that lays out a JSON document by the shape of the data instead of putting every single value on its own line.

This is the formatting engine behind jrp, the JSON Really Pretty CLI.

Why this exists

Every common pretty printer treats JSON as a list of members: one member, one line. That is fine for a small nested config, and terrible for everything else. A file of 200 flat records turns into 1400 lines of scroll, and a value you could have read at a glance is smeared over four lines:

{
    "id": 1,
    "name": "alpha",
    "scores": [
        10,
        20,
        30
    ],
    "active": true
}

Compact output (jq -c, JSON.stringify) has the opposite problem: it fits on one line, but nothing is readable.

jrp.Format picks the middle. The rule is a single one:

A container is written on one line unless it holds an object somewhere inside it.

So a plain record stays a single line however long it gets, while anything with real structure below it opens up and shows that structure. The same data:

[
    { "id": 1, "name": "alpha", "scores": [10, 20, 30], "active": true },
    { "id": 2, "name": "beta", "scores": [], "active": false },
    { "id": 3, "name": "gamma", "scores": [7], "active": null }
]

The result reads like a table where the data is tabular, and like a tree where the data is a tree — which is normally what you wanted to see in the first place.

A nested config behaves the same way. Leaf groups collapse, the structure that carries them stays open:

{
    "service": {
        "name": "gateway",
        "port": 8080,
        "tls": { "enabled": true, "ciphers": ["TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384"] }
    },
    "replicas": 3,
    "hosts": ["a.example.com", "b.example.com", "c.example.com"],
    "labels": { "tier": "edge" },
    "flags": [],
    "limits": { "cpu": "500m", "mem": "512Mi" }
}

Two more properties worth knowing:

  • The rewrite is textual, not a round trip through a decoded value. Key order and number formatting survive exactly as written — no 1e3 turning into 1000, no reordered members, no lost precision on big integers.
  • Format never mutates its input. It returns a new []byte; callers decide what to do with it (write to a file, respond over HTTP, etc.).

Usage

go get github.com/patrickbergner/json-really-pretty-go
import jrp "github.com/patrickbergner/json-really-pretty-go"

out, err := jrp.Format(src, jrp.Options{
    Indent:        "    ",
    SpaceInBraces: true,
})

jrp.Default() returns the options a bare-bones caller likely wants (4-space indent, spaced braces, trailing newline).

Options

Field Default Description
Indent "" The string used for one level of indentation in an expanded container, e.g. " " or "\t".
MaxWidth 0 Expand containers whose one-line form would pass this column. 0 disables.
MaxItems 0 Expand containers holding more than this many members or elements. 0 disables.
SpaceInBraces false Write inline objects as { "a": 1 } instead of {"a": 1}.
SpaceInBrackets false Write inline arrays as [ 1, 2 ] instead of [1, 2].
SortKeys false Sort object keys instead of keeping the input order.
TrailingNewline false Append a final newline to the output.
The two caps

The structural rule above is always in force and is not configurable — it is what the package is for. MaxWidth and MaxItems sit on top of it as optional ceilings for callers who do want a limit, and both are off by default.

  • MaxWidth: 40 expands anything whose single line would reach past column 40, so a long record falls back to conventional one-member-per-line output while its short neighbours stay inline. The cap is best effort: a single string literal longer than the limit still overflows, because JSON strings cannot be wrapped.
  • MaxItems: 3 expands anything with more than three members or elements, regardless of how short the line would be.

Both are measured over the whole subtree, so a container that is approved for one line keeps everything below it on that line too.

Style options

SpaceInBraces and SpaceInBrackets only affect inline containers. Turning both off ({"a": 1} and [1, 2]) still keeps objects and arrays visually distinct at a glance, since the bracket characters differ.

SortKeys is the only option that changes the data's presentation order; without it the input order is preserved byte for byte.

Building

Requires Go 1.24 or newer.

go build ./...
go test ./...

Documentation

Overview

Package jrp rewrites JSON documents with a layout that follows the shape of the data instead of putting every value on its own line.

A container collapses onto a single line unless it holds an object somewhere inside it, so a flat record stays readable as one line while anything with real structure below it opens up. Options.MaxItems and Options.MaxWidth add optional hard caps that fall back to conventional one-member-per-line output.

The rewrite is textual rather than a round trip through a Go value: key order and number formatting are preserved exactly as written, which re-marshalling a decoded value would not do.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Format

func Format(src []byte, opts Options) ([]byte, error)

Format reformats a JSON document according to opts.

Types

type Options

type Options struct {
	// Indent is one level of indentation in an expanded container.
	Indent string

	// MaxWidth, when greater than zero, expands any container whose one-line
	// form would reach past this column. Zero means no width limit.
	//
	// The limit is best effort: a single string literal longer than MaxWidth
	// still overflows its line, because JSON strings cannot be wrapped.
	MaxWidth int

	// MaxItems, when greater than zero, expands any container that holds more
	// than this many members or elements. Zero means no limit.
	MaxItems int

	// SpaceInBraces pads inline objects, as { "a": 1 } rather than {"a": 1}.
	SpaceInBraces bool

	// SpaceInBrackets pads inline arrays, as [ 1, 2 ] rather than [1, 2].
	SpaceInBrackets bool

	// SortKeys emits object members in lexicographic order instead of the
	// order they appear in the input.
	SortKeys bool

	// TrailingNewline appends a final newline to the output.
	TrailingNewline bool
}

Options controls how Format lays out a document.

The layout rule that gives the tool its name is not optional: a container collapses onto one line unless it holds an object somewhere inside it, so a plain record like { "id": 7, "name": "example" } stays a single line however long it gets, while anything with real structure below it opens up. MaxItems and MaxWidth sit on top of that as hard caps for people who do want a ceiling; both are off by default.

func Default

func Default() Options

Default returns the options the command line uses when given no flags.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL