• Stars
    star
    102
  • Rank 335,584 (Top 7 %)
  • Language
    Lua
  • License
    MIT License
  • Created over 9 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Pretty-print your JSON in Ruby, JS, or Lua with more power than JSON.stringify or JSON.pretty_generate

NeatJSON

Gem Version

Pretty-print your JSON in Ruby or JavaScript or Lua with more power than is provided by JSON.pretty_generate (Ruby) or JSON.stringify (JS). For example, like Ruby's pp (pretty print), NeatJSON can keep objects on one line if they fit, but break them over multiple lines if needed.

Features:

  • Online webpage for performing conversions and experimenting with options.
    • Modifying graphical options on the webpage also gives you the JS code you would need to call to get the same results.
  • Keep multiple values on one line, with variable wrap width.
  • Format numeric values to specified decimal precision.
    • Optionally force specific keys to use floating point representation instead of bare integers for whole number values (e.g. 42.0 instead of 42).
  • Sort object keys to be in alphabetical order.
  • Arbitrary whitespace (or really, any string) for indentation.
  • "Short" wrapping uses fewer lines, indentation based on values. (See last example below.)
  • Indent final closing bracket/brace for each array/object.
  • Adjust number of spaces inside array/object braces.
  • Adjust number of spaces before/after commas and colons (both for single- vs. multi-line).
  • Line up the values for an object across lines.
  • [Lua only] Produce Lua table serialization.

Table of Contents

Installation

  • Ruby: gem install neatjson
  • JavaScript (web): Clone the GitHub repo and copy javascript/neatjson.js
  • Node.js: npm install neatjson

Usage

Ruby:

require 'neatjson'
json = JSON.neat_generate( value, options )

JavaScript (web):

<script type="text/javascript" src="neatjson.js"></script>
<script type="text/javascript">
    var json = neatJSON( value, options );
</script>

Node.js:

const { neatJSON } = require('neatjson');
var json = neatJSON( value, options );

Lua:

local neatJSON = require'neatjson'
local json = neatJSON(value, options)

Examples

The following are all in Ruby, but similar options apply in JavaScript and Lua.

require 'neatjson'

o = { b:42.005, a:[42,17], longer:true, str:"yes\nplease" }

puts JSON.neat_generate(o)
#=> {"b":42.005,"a":[42,17],"longer":true,"str":"yes\nplease"}

puts JSON.neat_generate(o, sort:true)
#=> {"a":[42,17],"b":42.005,"longer":true,"str":"yes\nplease"}

puts JSON.neat_generate(o,sort:true,padding:1,after_comma:1)
#=> { "a":[ 42, 17 ], "b":42.005, "longer":true, "str":"yes\nplease" }

puts JSON.neat_generate(o, sort:true, wrap:40)
#=> {
#=>   "a":[42,17],
#=>   "b":42.005,
#=>   "longer":true,
#=>   "str":"yes\nplease"
#=> }

puts JSON.neat_generate(o, sort:true, wrap:40, decimals:2)
#=> {
#=>   "a":[42,17],
#=>   "b":42.01,
#=>   "longer":true,
#=>   "str":"yes\nplease"
#=> }

puts JSON.neat_generate(o, sort:->(k){ k.length }, wrap:40, aligned:true)
#=> {
#=>   "a"     :[42,17],
#=>   "b"     :42.005,
#=>   "str"   :"yes\nplease",
#=>   "longer":true
#=> }

puts JSON.neat_generate(o, sort:true, wrap:40, aligned:true, around_colon:1)
#=> {
#=>   "a"      : [42,17],
#=>   "b"      : 42.005,
#=>   "longer" : true,
#=>   "str"    : "yes\nplease"
#=> }

puts JSON.neat_generate(o, sort:true, wrap:40, aligned:true, around_colon:1, short:true)
#=> {"a"      : [42,17],
#=>  "b"      : 42.005,
#=>  "longer" : true,
#=>  "str"    : "yes\nplease"}

a = [1,2,[3,4,[5]]]
puts JSON.neat_generate(a)
#=> [1,2,[3,4,[5]]]

puts JSON.pretty_generate(a) # oof!
#=> [
#=>   1,
#=>   2,
#=>   [
#=>     3,
#=>     4,
#=>     [
#=>       5
#=>     ]
#=>   ]
#=> ]

puts JSON.neat_generate( a, wrap:true, short:true )
#=> [1,
#=>  2,
#=>  [3,
#=>   4,
#=>   [5]]]

data = ["foo","bar",{dogs:42,piggies:{color:'pink', tasty:true},
        barn:{jimmy:[1,2,3,4,5],jammy:3.141592653,hot:"pajammy"},cats:7}]

opts = { short:true, wrap:60, decimals:3, sort:true, aligned:true,
         padding:1, after_comma:1, around_colon_n:1 }

puts JSON.neat_generate( data, opts )
#=> [ "foo",
#=>   "bar",
#=>   { "barn"    : { "hot"   : "pajammy",
#=>                   "jammy" : 3.142,
#=>                   "jimmy" : [ 1, 2, 3, 4, 5 ] },
#=>     "cats"    : 7,
#=>     "dogs"    : 42,
#=>     "piggies" : { "color":"pink", "tasty":true } } ]

Options

You may pass any of the following options to neat_generate (Ruby) or neatJSON (JavaScript/Lua).

Note: camelCase option names below use snake_case in Ruby. For example:

// JavaScript
var json = neatJSON( myValue, { arrayPadding:1, afterComma:1, beforeColonN:2 } );
-- Lua
local json = neatJSON( myValue, { arrayPadding=1, afterComma=1, beforeColonN=2 } )
# Ruby
json = JSON.neat_generate my_value, array_padding:1, after_comma:1, before_colon_n:2
  • wrap โ€” Maximum line width before wrapping. Use false to never wrap, true to always wrap. default:80
  • indent โ€” Whitespace used to indent each level when wrapping. default:" " (two spaces)
  • indentLast โ€” Indent the closing bracket/brace for arrays and objects? default:false
  • short โ€” Put opening brackets on the same line as the first value, closing brackets on the same line as the last? default:false
    • This causes the indent and indentLast options to be ignored, instead basing indentation on array and object padding.
  • sort โ€” Sort objects' keys in alphabetical order (true), or supply a lambda for custom sorting. default:false
    • If you supply a lambda to the sort option, it will be passed three values: the (string) name of the key, the associated value, and the object being sorted, e.g. { sort:->(key,value,hash){ Float(value) rescue Float::MAX } }
  • aligned โ€” When wrapping objects, line up the colons (per object)? default:false
  • decimals โ€” Decimal precision for non-integer numbers; use false to keep values precise. default:false
  • trimTrailingZeros โ€” Remove extra zeros at the end of floats, e.g. 1.2000 becomes 1.2. default:false
  • forceFloats โ€” Force every integer value written to the file to be a float, e.g. 12 becomes 12.0. default:false
  • forceFloatsIn โ€” Specify an array of object key names under which all integer values are treated as floats. For example, serializing {a:[1, 2, {a:3, b:4}], c:{a:5, d:6} with forceFloatsIn:['a'] would produce {"a":[1.0, 2.0, {"a":3.0, "b":4}], "c":{"a":5.0, "d":6}}.
  • arrayPadding โ€” Number of spaces to put inside brackets for arrays. default:0
  • objectPadding โ€” Number of spaces to put inside braces for objects. default:0
  • padding โ€” Shorthand to set both arrayPadding and objectPadding. default:0
  • beforeComma โ€” Number of spaces to put before commas (for both arrays and objects). default:0
  • afterComma โ€” Number of spaces to put after commas (for both arrays and objects). default:0
  • aroundComma โ€” Shorthand to set both beforeComma and afterComma. default:0
  • beforeColon1 โ€” Number of spaces before a colon when the object is on one line. default:0
  • afterColon1 โ€” Number of spaces after a colon when the object is on one line. default:0
  • beforeColonN โ€” Number of spaces before a colon when the object is on multiple lines. default:0
  • afterColonN โ€” Number of spaces after a colon when the object is on multiple lines. default:0
  • beforeColon โ€” Shorthand to set both beforeColon1 and beforeColonN. default:0
  • afterColon โ€” Shorthand to set both afterColon1 and afterColonN. default:0
  • aroundColon โ€” Shorthand to set both beforeColon and afterColon. default:0
  • lua โ€” (Lua only) Output a Lua table literal instead of JSON? default:false
  • emptyTablesAreObjects โ€” (Lua only) Should {} in Lua become a JSON object ({}) or JSON array ([])? default:false (array)

You may omit the 'value' and/or 'object' parameters in your sort lambda if desired. For example:

# Ruby sorting examples
obj = {e:3, a:2, c:3, b:2, d:1, f:3}

JSON.neat_generate obj, sort:true                              # sort by key name
#=> {"a":2,"b":2,"c":3,"d":1,"e":3,"f":3}

JSON.neat_generate obj, sort:->(k){ k }                        # sort by key name (long way)
#=> {"a":2,"b":2,"c":3,"d":1,"e":3,"f":3}

JSON.neat_generate obj, sort:->(k,v){ [-v,k] }                 # sort by descending value, then by ascending key
#=> {"c":3,"e":3,"f":3,"a":2,"b":2,"d":1}

JSON.neat_generate obj, sort:->(k,v,h){ h.values.count(v) }    # sort by count of keys with same value
#=> {"d":1,"a":2,"b":2,"e":3,"c":3,"f":3}
// JavaScript sorting examples
var obj = {e:3, a:2, c:3, b:2, d:1, f:3};

neatJSON( obj, {sort:true} );                                              // sort by key name
// {"a":2,"b":2,"c":3,"d":1,"e":3,"f":3}

neatJSON( obj, { sort:function(k){ return k }} );                          // sort by key name (long way)
// {"a":2,"b":2,"c":3,"d":1,"e":3,"f":3}

neatJSON( obj, { sort:function(k,v){ return -v }} );                       // sort by descending value
// {"e":3,"c":3,"f":3,"a":2,"b":2,"d":1}

var countByValue = {};
for (var k in obj) countByValue[obj[k]] = (countByValue[obj[k]]||0) + 1;
neatJSON( obj, { sort:function(k,v){ return countByValue[v] } } );         // sort by count of same value
// {"d":1,"a":2,"b":2,"e":3,"c":3,"f":3}

Note that the JavaScript and Lua versions of NeatJSON do not provide a mechanism for cascading sort in the same manner as Ruby.

License & Contact

NeatJSON is copyright ยฉ2015โ€“2023 by Gavin Kistner and is released under the MIT License. See the LICENSE.txt file for more details.

For bugs or feature requests please open issues on GitHub. For other communication you can email the author directly.

TODO (aka Known Limitations)

  • [Ruby] Figure out the best way to play with custom objects that use to_json for their representation.
  • Detect circular references.
  • Possibly allow "JSON5" output (legal identifiers unquoted, etc.)

History

  • v0.10.6 โ€” March 17, 2023

    • Add TypeScript definitions for JavaScript library
  • v0.10.5 โ€” November 17, 2022

    • Fix issue #21: Strings containing # get an invalid escape added (Ruby only)
  • v0.10.4 โ€” November 17, 2022

    • Online tool shows input/output bytes
  • v0.10.2 โ€” August 31, 2022

    • Fix bugs found in JavaScript version related to trim_trailing_zeros.
  • v0.10.1 โ€” August 29, 2022

    • Fix bugs found when force_floats_in was combined with wrapping.
    • Update interactive HTML tool to support new features.
  • v0.10 โ€” August 29, 2022

    • Add force_floats and force_floats_in to support serialization for non-standard parsers that differentiate between integers and floats.
    • Add trim_trailing_zeros option to convert the decimals output from e.g. 5.40000 to 5.4.
    • Convert JavaScript version to require ECMAScript 6 for performance.
  • v0.9 โ€” July 29, 2019

    • Add Lua version, serializing to both JSON and Lua table literals
    • All languages serialize Infinity/-Infinity to JSON as 9e9999 and -9e9999
    • All languages serialize NaN to JSON as "NaN"
  • v0.8.4 โ€” May 3, 2018

    • Fix issue #27: Default sorting fails with on objects with mixed keys [Ruby only]
      • Thanks Reid Beels
  • v0.8.3 โ€” February 20, 2017

    • Fix issue #25: Sorting keys on multi-line object using function does not work without "short" [JS only]
      • Thanks Bernhard Weichel
  • v0.8.2 โ€” December 16th, 2016

    • Fix issue #22: Sorting keys on multi-line object does not work without "short" [JS only]
    • Update online interface to support tabs as well as spaces.
    • Update online interface to use a textarea for the output (easier to select and copy).
    • Update online interface turn off spell checking for input and output.
  • v0.8.1 โ€” April 22nd, 2016

    • Make NeatJSON work with Opal (by removing all in-place string mutations)
  • v0.8 โ€” April 21st, 2016

    • Allow sort to take a lambda for customized sorting of object key/values.
  • v0.7.2 โ€” April 14th, 2016

    • Fix JavaScript library to support objects without an Object constructor (e.g. location).
    • Online HTML converter accepts arbitrary JavaScript values as input in addition to JSON.
  • v0.7.1 โ€” April 6th, 2016

    • Fix Ruby library to work around bug in Opal.
  • v0.7 โ€” March 26th, 2016

    • Add indentLast/indent_last feature.
  • v0.6.2 โ€” February 8th, 2016

    • Use memoization to avoid performance stalls when wrapping deeply-nested objects/arrays. Thanks @chroche
  • v0.6.1 โ€” October 12th, 2015

    • Fix handling of nested empty objects and arrays. (Would cause a runtime error in many cases.)
      • This change causes empty arrays in a tight wrapping scenario to appear on a single line where they would previously take up three lines.
  • v0.6 โ€” April 26th, 2015

    • Added before_colon_1 and before_colon_n to distinguish between single-line and multi-line objects.
  • v0.5 โ€” April 19th, 2015

    • Do not format integers (or floats that equal their integer) using decimals option.
    • Make neatJSON() JavaScript available to Node.js as well as web browsers.
    • Add (Node-based) testing for the JavaScript version.
  • v0.4 โ€” April 18th, 2015

    • Add JavaScript version with online runner.
  • v0.3.2 โ€” April 16th, 2015

    • Force YARD to use Markdown for documentation.
  • v0.3.1 โ€” April 16th, 2015

    • Remove some debugging code accidentally left in.
  • v0.3 โ€” April 16th, 2015

    • Fix another bug with short:true and wrapping array values inside objects.
  • v0.2 โ€” April 16th, 2015

    • Fix bug with short:true and wrapping values inside objects.
  • v0.1 โ€” April 15th, 2015

    • Initial release.

More Repositories

1

context-blender

Photoshop-style blend modes for HTML Canvas Contexts
JavaScript
619
star
2

riblits

Shell for new Sinatra Applications
Ruby
160
star
3

SLAXML

SAX-like streaming XML parser for Lua
Lua
148
star
4

svg2geojson

Converts an SVG file with added geo-referencing tags into one or more GeoJSON files.
JavaScript
54
star
5

svg-path-to-polygons

Converts path commands for an SVG path to polygon points.
JavaScript
53
star
6

LXSC

Lua XML StateChart interpreter - parses and executes SCXML state machines with a Lua data model.
Lua
36
star
7

docubot

Create CHM documentation from simple hierarchy of plain text files.
Ruby
24
star
8

Lunity

Simple-but-rich unit testing for Lua
Lua
22
star
9

PEGSH

Realtime PEG Syntax Highlighting in a web browser
JavaScript
16
star
10

visual-scxml-editor

VS Code extension for visualizing and graphically editing SCXML statecharts
JavaScript
8
star
11

rb3jay

Democratic crowd-controlled office music player.
JavaScript
6
star
12

omnifense

2-player, turn-based, offense/defense pseudo-tower-defense-style game. Sort of.
JavaScript
4
star
13

RXSC

Ruby XML StateChart machine for running W3C SCXML files with a Ruby data model in a non-threaded manner.
Ruby
4
star
14

notifitable

Lua tables that notify you when specific values have changed.
Lua
4
star
15

liqrrdmetal

Calculate scoring of autocomplete-style substring matches, identifying which portions of the string were matched.
Ruby
3
star
16

DrumSaber

RGB LED lighting effects generated by live drumming.
C++
2
star
17

d3hierarchy

Structured Documentation for the D3.js objects
2
star
18

Flooph

A simple, safe, sandbox for evaluating simple conditionals, expressions, and templates.
Ruby
1
star
19

ZSS

A pure Lua library that parses (limited) CSS rules and computes the declarations to apply to elements.
Lua
1
star
20

Liqr

Substring filtering for Lua
Lua
1
star
21

SCXMLEditor

Simple web-based editor for SCXML
JavaScript
1
star
22

RUIC

Ruby API for NVIDIA's UI Composer, with a mini DSL for easy analysis and manipulation.
Ruby
1
star
23

Docdo

Generic Ruby document management with lightweight undo/redo stacks.
Ruby
1
star
24

BubbleDiagram

Qt/QML-based interactive architecture space layout
QML
1
star
25

hatshuffler

Creating seasons of hat tournaments that are diverse and fair.
JavaScript
1
star
26

laink

Game server handling remote AI clients playing turn-based games over TCP Sockets and JSON.
Ruby
1
star
27

Khronic

YAML-based mod tracker music for Ruby.
Ruby
1
star
28

SmoothedOdometry

Simply fusing together robot odometry and external measurements in a quick, "good enough" fashion.
JavaScript
1
star