json-tight

A JSON pretty-printer for Crystal that keeps output compact without sacrificing readability. Standard pretty-printing puts every element on its own line, so a small array of numbers can eat a full screen. json-tight fits each collection to a width budget instead, choosing the tightest layout that still reads well:

  1. Single line — the whole collection, when it fits within the width.
  2. Columnar — elements laid out in aligned columns, when each element is individually short. Numbers are right-aligned within their column; everything else is left-aligned.
  3. Expanded — one element per line, indented, when nothing tighter fits.

The choice is made per collection, so a document mixes layouts naturally:

{
  "name": "example",
  "values": [ 1, 2, 3 ],
  "nested": {
    "deep": [  10, 20, 30, 40, 50, 60, 70, 80, 90,
              100 ],
    "flag": true
  }
}

The width budget applies to content only; leading indentation is not counted.

Installation

  1. Add the dependency to your shard.yml:

    dependencies:
      json-tight:
        github: plambert/json-tight.cr
  2. Run shards install

Usage

require "json-tight"

# From a JSON::Any (e.g. the result of JSON.parse):
puts JSON::Tight.generate(JSON.parse(input), width: 60)

# From any value that responds to #to_json, including JSON::Serializable types:
puts JSON::Tight.generate({"name" => "example", "sizes" => [1, 2, 3]})

# From a string of JSON (a bare positional String would be formatted as a
# JSON string scalar, so raw JSON is passed by name):
puts JSON::Tight.generate(json: %({"a": 1, "b": [2, 3]}))

# Each form also accepts an IO as the first argument:
JSON::Tight.generate(STDOUT, value, width: 100)

# Or build a Formatter to control the indent used by expanded layouts:
formatter = JSON::Tight::Formatter.new(width: 100, indent: 4)
formatter.format(STDOUT, value)

width defaults to 80 and indent to 2.

Development

shards install                 # fetch development dependencies (Spectator)
crystal spec -v --error-trace  # run the test suite
crystal tool format            # format before committing
ameba                          # lint

Contributing

  1. Fork it (https://github.com/plambert/json-tight.cr/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors