1 `jju` - a set of utilities to work with JSON / JSON5 documents
3 [![npm version badge](https://img.shields.io/npm/v/jju.svg)](https://www.npmjs.org/package/jju)
4 [![travis badge](http://img.shields.io/travis/rlidwka/jju.svg)](https://travis-ci.org/rlidwka/jju)
5 [![downloads badge](http://img.shields.io/npm/dm/jju.svg)](https://www.npmjs.org/package/jju)
15 This module provides following functions:
17 1. [jju.parse()](#jjuparse-function) parses json/json5 text and returns a javascript value it corresponds to
18 2. [jju.stringify()](#jjustringify-function) converts javascript value to an appropriate json/json5 text
19 3. [jju.tokenize()](#jjutokenize-function) parses json/json5 text and returns an array of tokens it consists of ([see demo](http://rlidwka.github.io/jju/tokenizer.html))
20 4. [jju.analyze()](#jjuanalyze-function) parses json/json5 text and tries to guess indentation, quoting style, etc.
21 5. [jju.update()](#jjuupdate-function) changes json/json5 text, preserving original formatting as much as possible ([see demo](http://rlidwka.github.io/jju/editor.html))
23 All functions are able to work with a standard JSON documents. `jju.parse()` and `jju.stringify()` are better in some cases, but slower than native `JSON.parse()` and `JSON.stringify()` versions. Detailed description see below.
25 ### jju.parse() function
31 * `text` - text to parse, type: String
32 * `options` - parser options, type: Object
34 jju.parse(text[, options])
36 // compatibility syntax
37 jju.parse(text[, reviver])
42 - reserved\_keys - what to do with reserved keys (String, default="ignore")
43 - "ignore" - ignore reserved keys
44 - "throw" - throw SyntaxError in case of reserved keys
45 - "replace" - replace reserved keys, this is the default JSON.parse behaviour, unsafe
47 Reserved keys are keys that exist in an empty object (`hasOwnProperty`, `__proto__`, etc.).
50 // 'ignore' will cause reserved keys to be ignored:
51 parse('{hasOwnProperty: 1}', {reserved_keys: 'ignore'}) == {}
52 parse('{hasOwnProperty: 1, x: 2}', {reserved_keys: 'ignore'}).hasOwnProperty('x') == true
54 // 'throw' will cause SyntaxError in these cases:
55 parse('{hasOwnProperty: 1}', {reserved_keys: 'throw'}) == SyntaxError
57 // 'replace' will replace reserved keys with new ones:
58 parse('{hasOwnProperty: 1}', {reserved_keys: 'throw'}) == {hasOwnProperty: 1}
59 parse('{hasOwnProperty: 1, x: 2}', {reserved_keys: 'ignore'}).hasOwnProperty('x') == TypeError
63 - null\_prototype - create object as Object.create(null) instead of '{}' (Boolean)
65 if `reserved_keys != 'replace'`, default is **false**
67 if `reserved_keys == 'replace'`, default is **true**
69 It is usually unsafe and not recommended to change this option to false in the last case.
71 - reviver - reviver function - Function
73 This function should follow JSON specification
75 - mode - operation mode, set it to 'json' if you want to throw on non-strict json files (String)
77 ### jju.stringify() function
83 * `value` - value to serialize, type: *
84 * `options` - serializer options, type: Object
86 jju.stringify(value[, options])
88 // compatibility syntax
89 jju.stringify(value[, replacer [, indent])
94 - ascii - output ascii only (Boolean, default=false)
95 If this option is enabled, output will not have any characters except of 0x20-0x7f.
97 - indent - indentation (String, Number or Boolean, default='\t')
98 This option follows JSON specification.
100 - quote - enquoting char (String, "'" or '"', default="'")
101 - quote\_keys - whether keys quoting in objects is required or not (String, default=false)
102 If you want `{"q": 1}` instead of `{q: 1}`, set it to true.
104 - sort\_keys - sort all keys while stringifying (Boolean or Function, default=false)
105 By default sort order will depend on implementation, with v8 it's insertion order. If set to `true`, all keys (but not arrays) will be sorted alphabetically. You can provide your own sorting function as well.
107 - replacer - replacer function or array (Function or Array)
108 This option follows JSON specification.
110 - no\_trailing\_comma = don't output trailing comma (Boolean, default=false)
111 If this option is set, arrays like this `[1,2,3,]` will never be generated. Otherwise they may be generated for pretty printing.
113 - mode - operation mode, set it to 'json' if you want correct json in the output (String)
115 Currently it's either 'json' or something else. If it is 'json', following options are implied:
117 - options.quote = '"'
118 - options.no\_trailing\_comma = true
119 - options.quote\_keys = true
120 - '\x' literals are not used
122 ### jju.tokenize() function
128 * `text` - text to tokenize, type: String
129 * `options` - parser options, type: Object
131 jju.tokenize(text[, options])
134 Options are the same as for the `jju.parse` function.
136 Return value is an array of tokens, where each token is an object:
138 - raw (String) - raw text of this token, if you join all raw's, you will get the original document
139 - type (String) - type of the token, can be `whitespace`, `comment`, `key`, `literal`, `separator` or `newline`
140 - stack (Array) - path to the current token in the syntax tree
141 - value - value of the token if token is a `key` or `literal`
143 You can check tokenizer for yourself using [this demo](http://rlidwka.github.io/jju/tokenizer.html).
145 ### jju.analyze() function
151 * `text` - text to analyze, type: String
152 * `options` - parser options, type: Object
154 jju.analyze(text[, options])
157 Options are the same as for the `jju.parse` function.
159 Return value is an object defining a programming style in which the document was written.
161 - indent (String) - preferred indentation
162 - newline (String) - preferred newline
163 - quote (String) - `"` or `'` depending on which quote is preferred
164 - quote\_keys (Boolean) - `true` if unquoted keys were used at least once
165 - has\_whitespace (Boolean) - `true` if input has a whitespace token
166 - has\_comments (Boolean) - `true` if input has a comment token
167 - has\_newlines (Boolean) - `true` if input has a newline token
168 - has\_trailing\_comma (Boolean) - `true` if input has at least one trailing comma
170 ### jju.update() function
176 * `text` - original text, type: String
177 * `new_value` - new value you want to set
178 * `options` - parser or stringifier options, type: Object
180 jju.update(text, new_value[, options])
183 If you want to update a JSON document, here is the general approach:
186 // here is your original JSON document:
187 var input = '{"foo": "bar", "baz": 123}'
189 // you need to parse it first:
190 var json = jju.parse(input, {mode: 'json'})
191 // json is { foo: 'bar', baz: 123 }
193 // then you can change it as you like:
197 // then you run an update function to change the original json:
198 var output = jju.update(input, json, {mode: 'json'})
199 // output is '{"foo": "quux", "baz": 123, "hello": "world"}'
202 Look at [this demo](http://rlidwka.github.io/jju/editor.html) to test various types of json.
204 ## Advantages over existing JSON libraries
206 In a few cases it makes sense to use this module instead of built-in JSON methods.
209 - better error reporting with source code and line numbers
211 In case of syntax error, JSON.parse does not return any good information to the user. This module does:
214 $ node -e 'require("jju").parse("[1,1,1,1,invalid]")'
216 SyntaxError: Unexpected token 'i' at 0:9
221 This module is about 5 times slower, so if user experience matters to you more than performance, use this module. If you're working with a lot of machine-generated data, use JSON.parse instead.
224 - util.inspect-like pretty printing
226 This module behaves more smart when dealing with object and arrays, and does not always print newlines in them:
229 $ node -e 'console.log(require("./").stringify([[,,,],,,[,,,,]], {mode:"json"}))'
234 [null, null, null, null]
238 JSON.stringify will split this into 15 lines, and it's hard to read.
240 Yet again, this feature comes with a performance hit, so if user experience matters to you more than performance, use this module. If your JSON will be consumed by machines, use JSON.stringify instead.
242 As a rule of thumb, if you use "space" argument to indent your JSON, you'd better use this module instead.