Comparing version
@@ -6,6 +6,36 @@ ### Unreleased [[code][cNew], [diff][dNew]] | ||
These changes are sitting unreleased on the `develop` branch: | ||
- (Nothing yet.) | ||
### v0.4.0 [[code][c0.4.0], [diff][d0.4.0]] | ||
[c0.4.0]: https://github.com/aseemk/json5/tree/v0.4.0 | ||
[d0.4.0]: https://github.com/aseemk/json5/compare/v0.2.0...v0.4.0 | ||
Note that v0.3.0 was tagged, but never published to npm, so this v0.4.0 | ||
changelog entry includes v0.3.0 features. | ||
This is a massive release that adds `stringify` support, among other things. | ||
- **Major:** `JSON5.stringify()` now exists! | ||
This method is analogous to the native `JSON.stringify()`; | ||
it just avoids quoting keys where possible. | ||
See the [usage documentation](./README.md#usage) for more. | ||
([#32][]; huge thanks and props [@aeisenberg][]!) | ||
- New: `NaN` and `-NaN` are now allowed number literals. | ||
([#30][]; thanks [@rowanhill][].) | ||
- New: Duplicate object keys are now allowed; the last value is used. | ||
This is the same behavior as JSON. ([#57][]; thanks [@jordanbtucker][].) | ||
- Fix: Properly handle various whitespace and newline cases now. | ||
E.g. JSON5 now properly supports escaped CR and CRLF newlines in strings, | ||
and JSON5 now accepts the same whitespace as JSON (stricter than ES5). | ||
([#58][], [#60][], and [#63][]; thanks [@jordanbtucker][].) | ||
- New: Negative hexadecimal numbers (e.g. `-0xC8`) are allowed again. | ||
(They were disallowed in v0.2.0; see below.) | ||
It turns out they *are* valid in ES5, so JSON5 supports them now too. | ||
([#36][]; thanks [@jordanbtucker][]!) | ||
### v0.2.0 [[code][c0.2.0], [diff][d0.2.0]] | ||
@@ -24,24 +54,17 @@ | ||
[v8-hex-fix]: http://code.google.com/p/v8/issues/detail?id=2240 | ||
[#36]: https://github.com/aseemk/json5/issues/36 | ||
- **Breaking:** Trailing decimal points in decimal numbers are allowed again. | ||
- New: Trailing decimal points in decimal numbers are allowed again. | ||
(They were disallowed in v0.1.0; see below.) | ||
They're allowed by ES5, and differentiating between integers and floats may | ||
make sense on some platforms. ([#16][]; thanks [@Midar][].) | ||
[#16]: https://github.com/aseemk/json5/issues/16 | ||
- **New:** `Infinity` and `-Infinity` are now allowed number literals. | ||
- New: `Infinity` and `-Infinity` are now allowed number literals. | ||
([#30][]; thanks [@pepkin88][].) | ||
[#30]: https://github.com/aseemk/json5/issues/30 | ||
- **New:** Plus signs (`+`) in front of numbers are now allowed, since it can | ||
- New: Plus signs (`+`) in front of numbers are now allowed, since it can | ||
be helpful in some contexts to explicitly mark numbers as positive. | ||
(E.g. when a property represents changes or deltas.) | ||
- Bug fix: unescaped newlines in strings are rejected now. ([#24][]; thanks | ||
[@Midar][].) | ||
- Fix: unescaped newlines in strings are rejected now. | ||
([#24][]; thanks [@Midar][].) | ||
[#24]: https://github.com/aseemk/json5/issues/24 | ||
@@ -55,5 +78,5 @@ ### v0.1.0 [[code][c0.1.0], [diff][d0.1.0]] | ||
- Support hexadecimal numbers. (Thanks [@MaxNanasy][].) | ||
- New: Support hexadecimal numbers. (Thanks [@MaxNanasy][].) | ||
- Reject octal numbers properly now. Previously, they were accepted but | ||
- Fix: Reject octal numbers properly now. Previously, they were accepted but | ||
improperly parsed as base-10 numbers. (Thanks [@MaxNanasy][].) | ||
@@ -65,3 +88,4 @@ | ||
- Support leading decimal points in decimal numbers. (Thanks [@MaxNanasy][].) | ||
- New: Support leading decimal points in decimal numbers. | ||
(Thanks [@MaxNanasy][].) | ||
@@ -74,8 +98,9 @@ - **Breaking:** Reject trailing decimal points in decimal numbers now. These | ||
- Throw proper `SyntaxError` instances on errors now. | ||
- Fix: Throw proper `SyntaxError` instances on errors now. | ||
- Add Node.js `require()` hook. Require `json5/lib/require` to register it. | ||
- New: Add Node.js `require()` hook. Register via `json5/lib/require`. | ||
- Add Node.js executable to compile JSON5 files to JSON. Run with `json5`. | ||
- New: Add Node.js `json5` executable to compile JSON5 files to JSON. | ||
### v0.0.1 [[code][c0.0.1], [diff][d0.0.1]] | ||
@@ -99,2 +124,3 @@ | ||
### v0.0.0 [[code](https://github.com/aseemk/json5/tree/v0.0.0)] | ||
@@ -105,3 +131,5 @@ | ||
[json_parse.js]: https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js | ||
[v8-hex-fix]: http://code.google.com/p/v8/issues/detail?id=2240 | ||
@@ -111,1 +139,14 @@ [@MaxNanasy]: https://github.com/MaxNanasy | ||
[@pepkin88]: https://github.com/pepkin88 | ||
[@rowanhill]: https://github.com/rowanhill | ||
[@aeisenberg]: https://github.com/aeisenberg | ||
[@jordanbtucker]: https://github.com/jordanbtucker | ||
[#16]: https://github.com/aseemk/json5/issues/16 | ||
[#24]: https://github.com/aseemk/json5/issues/24 | ||
[#30]: https://github.com/aseemk/json5/issues/30 | ||
[#32]: https://github.com/aseemk/json5/issues/32 | ||
[#36]: https://github.com/aseemk/json5/issues/36 | ||
[#57]: https://github.com/aseemk/json5/issues/57 | ||
[#58]: https://github.com/aseemk/json5/pull/58 | ||
[#60]: https://github.com/aseemk/json5/pull/60 | ||
[#63]: https://github.com/aseemk/json5/pull/63 |
297
lib/json5.js
@@ -34,2 +34,12 @@ // json5.js | ||
}, | ||
ws = [ | ||
' ', | ||
'\t', | ||
'\r', | ||
'\n', | ||
'\v', | ||
'\f', | ||
'\xA0', | ||
'\uFEFF' | ||
], | ||
text, | ||
@@ -64,2 +74,10 @@ | ||
peek = function () { | ||
// Get the next character without consuming it or | ||
// assigning it to the ch varaible. | ||
return text.charAt(at); | ||
}, | ||
identifier = function () { | ||
@@ -106,3 +124,3 @@ | ||
if (ch === '-' || ch === '+') { | ||
sign = string = ch; | ||
sign = ch; | ||
next(ch); | ||
@@ -120,2 +138,12 @@ } | ||
// support for NaN | ||
if (ch === 'N' ) { | ||
number = word(); | ||
if (!isNaN(number)) { | ||
error('expected word to be NaN'); | ||
} | ||
// ignore sign as -NaN also is NaN | ||
return number; | ||
} | ||
if (ch === '0') { | ||
@@ -133,7 +161,2 @@ string += ch; | ||
// https://github.com/aseemk/json5/issues/36 | ||
if (base === 16 && sign) { | ||
error('Signed hexadecimal literal'); | ||
} | ||
switch (base) { | ||
@@ -171,3 +194,9 @@ case 10: | ||
} | ||
number = +string; | ||
if(sign === '-') { | ||
number = -string; | ||
} else { | ||
number = +string; | ||
} | ||
if (!isFinite(number)) { | ||
@@ -210,2 +239,6 @@ error("Bad number"); | ||
string += String.fromCharCode(uffff); | ||
} else if (ch === '\r') { | ||
if (peek() === '\n') { | ||
next(); | ||
} | ||
} else if (typeof escapee[ch] === 'string') { | ||
@@ -242,4 +275,4 @@ string += escapee[ch]; | ||
next(); | ||
if (ch === '\n') { | ||
next('\n'); | ||
if (ch === '\n' || ch === '\r') { | ||
next(); | ||
return; | ||
@@ -305,3 +338,3 @@ } | ||
comment(); | ||
} else if (ch <= ' ') { | ||
} else if (ws.indexOf(ch) >= 0) { | ||
next(); | ||
@@ -348,2 +381,7 @@ } else { | ||
return Infinity; | ||
case 'N': | ||
next( 'N' ); | ||
next( 'a' ); | ||
next( 'N' ); | ||
return NaN; | ||
} | ||
@@ -416,5 +454,2 @@ error("Unexpected '" + ch + "'"); | ||
next(':'); | ||
if (Object.hasOwnProperty.call(object, key)) { | ||
error('Duplicate key "' + key + '"'); | ||
} | ||
object[key] = value(); | ||
@@ -464,3 +499,3 @@ white(); | ||
text = source; | ||
text = String(source); | ||
at = 0; | ||
@@ -499,6 +534,234 @@ ch = ' '; | ||
// JSON5 stringify will not quote keys where appropriate | ||
JSON5.stringify = function (obj, replacer, space) { | ||
// Since regular JSON is a strict subset of JSON5, we'll always output | ||
// regular JSON to foster better interoperability. TODO Should we not? | ||
return JSON.stringify.apply(JSON, arguments); | ||
if (replacer && (typeof(replacer) !== "function" && !isArray(replacer))) { | ||
throw new Error('Replacer must be a function or an array'); | ||
} | ||
var getReplacedValueOrUndefined = function(holder, key, isTopLevel) { | ||
var value = holder[key]; | ||
// Replace the value with its toJSON value first, if possible | ||
if (value && value.toJSON && typeof value.toJSON === "function") { | ||
value = value.toJSON(); | ||
} | ||
// If the user-supplied replacer if a function, call it. If it's an array, check objects' string keys for | ||
// presence in the array (removing the key/value pair from the resulting JSON if the key is missing). | ||
if (typeof(replacer) === "function") { | ||
return replacer.call(holder, key, value); | ||
} else if(replacer) { | ||
if (isTopLevel || isArray(holder) || replacer.indexOf(key) >= 0) { | ||
return value; | ||
} else { | ||
return undefined; | ||
} | ||
} else { | ||
return value; | ||
} | ||
}; | ||
function isWordChar(char) { | ||
return (char >= 'a' && char <= 'z') || | ||
(char >= 'A' && char <= 'Z') || | ||
(char >= '0' && char <= '9') || | ||
char === '_' || char === '$'; | ||
} | ||
function isWordStart(char) { | ||
return (char >= 'a' && char <= 'z') || | ||
(char >= 'A' && char <= 'Z') || | ||
char === '_' || char === '$'; | ||
} | ||
function isWord(key) { | ||
if (typeof key !== 'string') { | ||
return false; | ||
} | ||
if (!isWordStart(key[0])) { | ||
return false; | ||
} | ||
var i = 1, length = key.length; | ||
while (i < length) { | ||
if (!isWordChar(key[i])) { | ||
return false; | ||
} | ||
i++; | ||
} | ||
return true; | ||
} | ||
// export for use in tests | ||
JSON5.isWord = isWord; | ||
// polyfills | ||
function isArray(obj) { | ||
if (Array.isArray) { | ||
return Array.isArray(obj); | ||
} else { | ||
return Object.prototype.toString.call(obj) === '[object Array]'; | ||
} | ||
} | ||
function isDate(obj) { | ||
return Object.prototype.toString.call(obj) === '[object Date]'; | ||
} | ||
isNaN = isNaN || function(val) { | ||
return typeof val === 'number' && val !== val; | ||
}; | ||
var objStack = []; | ||
function checkForCircular(obj) { | ||
for (var i = 0; i < objStack.length; i++) { | ||
if (objStack[i] === obj) { | ||
throw new TypeError("Converting circular structure to JSON"); | ||
} | ||
} | ||
} | ||
function makeIndent(str, num, noNewLine) { | ||
if (!str) { | ||
return ""; | ||
} | ||
// indentation no more than 10 chars | ||
if (str.length > 10) { | ||
str = str.substring(0, 10); | ||
} | ||
var indent = noNewLine ? "" : "\n"; | ||
for (var i = 0; i < num; i++) { | ||
indent += str; | ||
} | ||
return indent; | ||
} | ||
var indentStr; | ||
if (space) { | ||
if (typeof space === "string") { | ||
indentStr = space; | ||
} else if (typeof space === "number" && space >= 0) { | ||
indentStr = makeIndent(" ", space, true); | ||
} else { | ||
// ignore space parameter | ||
} | ||
} | ||
// Copied from Crokford's implementation of JSON | ||
// See https://github.com/douglascrockford/JSON-js/blob/e39db4b7e6249f04a195e7dd0840e610cc9e941e/json2.js#L195 | ||
// Begin | ||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, | ||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, | ||
meta = { // table of character substitutions | ||
'\b': '\\b', | ||
'\t': '\\t', | ||
'\n': '\\n', | ||
'\f': '\\f', | ||
'\r': '\\r', | ||
'"' : '\\"', | ||
'\\': '\\\\' | ||
}; | ||
function escapeString(string) { | ||
// If the string contains no control characters, no quote characters, and no | ||
// backslash characters, then we can safely slap some quotes around it. | ||
// Otherwise we must also replace the offending characters with safe escape | ||
// sequences. | ||
escapable.lastIndex = 0; | ||
return escapable.test(string) ? '"' + string.replace(escapable, function (a) { | ||
var c = meta[a]; | ||
return typeof c === 'string' ? | ||
c : | ||
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); | ||
}) + '"' : '"' + string + '"'; | ||
} | ||
// End | ||
function internalStringify(holder, key, isTopLevel) { | ||
var buffer, res; | ||
// Replace the value, if necessary | ||
var obj_part = getReplacedValueOrUndefined(holder, key, isTopLevel); | ||
if (obj_part && !isDate(obj_part)) { | ||
// unbox objects | ||
// don't unbox dates, since will turn it into number | ||
obj_part = obj_part.valueOf(); | ||
} | ||
switch(typeof obj_part) { | ||
case "boolean": | ||
return obj_part.toString(); | ||
case "number": | ||
if (isNaN(obj_part) || !isFinite(obj_part)) { | ||
return "null"; | ||
} | ||
return obj_part.toString(); | ||
case "string": | ||
return escapeString(obj_part.toString()); | ||
case "object": | ||
if (obj_part === null) { | ||
return "null"; | ||
} else if (isArray(obj_part)) { | ||
checkForCircular(obj_part); | ||
buffer = "["; | ||
objStack.push(obj_part); | ||
for (var i = 0; i < obj_part.length; i++) { | ||
res = internalStringify(obj_part, i, false); | ||
buffer += makeIndent(indentStr, objStack.length); | ||
if (res === null || typeof res === "undefined") { | ||
buffer += "null"; | ||
} else { | ||
buffer += res; | ||
} | ||
if (i < obj_part.length-1) { | ||
buffer += ","; | ||
} else if (indentStr) { | ||
buffer += "\n"; | ||
} | ||
} | ||
objStack.pop(); | ||
buffer += makeIndent(indentStr, objStack.length, true) + "]"; | ||
} else { | ||
checkForCircular(obj_part); | ||
buffer = "{"; | ||
var nonEmpty = false; | ||
objStack.push(obj_part); | ||
for (var prop in obj_part) { | ||
if (obj_part.hasOwnProperty(prop)) { | ||
var value = internalStringify(obj_part, prop, false); | ||
isTopLevel = false; | ||
if (typeof value !== "undefined" && value !== null) { | ||
buffer += makeIndent(indentStr, objStack.length); | ||
nonEmpty = true; | ||
var key = isWord(prop) ? prop : escapeString(prop); | ||
buffer += key + ":" + (indentStr ? ' ' : '') + value + ","; | ||
} | ||
} | ||
} | ||
objStack.pop(); | ||
if (nonEmpty) { | ||
buffer = buffer.substring(0, buffer.length-1) + makeIndent(indentStr, objStack.length) + "}"; | ||
} else { | ||
buffer = '{}'; | ||
} | ||
} | ||
return buffer; | ||
default: | ||
// functions and undefined should be ignored | ||
return undefined; | ||
} | ||
} | ||
// special case...when undefined is used inside of | ||
// a compound object/array, return null. | ||
// but when top-level, return undefined | ||
var topLevelHolder = {"":obj}; | ||
if (obj === undefined) { | ||
return getReplacedValueOrUndefined(topLevelHolder, '', true); | ||
} | ||
return internalStringify(topLevelHolder, '', true); | ||
}; |
{ | ||
"name": "json5", | ||
"version": "0.2.0", | ||
"version": "0.4.0", | ||
"description": "JSON for the ES5 era.", | ||
@@ -10,4 +10,6 @@ "keywords": [ | ||
"author": "Aseem Kishore <aseem.kishore@gmail.com>", | ||
"license": "MIT", | ||
"contributors": [ | ||
"Max Nanasy <max.nanasy@gmail.com>" | ||
"Max Nanasy <max.nanasy@gmail.com>", | ||
"Andrew Eisenberg <andrew@eisenberg.as>" | ||
], | ||
@@ -14,0 +16,0 @@ "main": "lib/json5.js", |
163
README.md
[](https://travis-ci.org/aseemk/json5) | ||
# JSON5 – Modern JSON | ||
JSON isn't the friendliest to write and maintain by hand. Keys need to be | ||
quoted; objects and arrays can't have trailing commas; comments aren't | ||
supported — even though none of these are the case with regular JavaScript | ||
today. | ||
JSON is an excellent data format, but we think it can be better. | ||
Restricting JSON to such a strict subset of "JavaScript object notation" made | ||
sense for making it a great data-exchange format, but JSON's usage has | ||
expanded [beyond][ex1] [machine-to-machine][ex2] [communication][ex3]. | ||
**JSON5 is a proposed extension to JSON** that aims to make it easier for | ||
*humans to write and maintain* by hand. It does this by adding some minimal | ||
syntax features directly from ECMAScript 5. | ||
JSON5 remains a **strict subset of JavaScript**, adds **no new data types**, | ||
and **works with all existing JSON content**. | ||
JSON5 is *not* an official successor to JSON, and JSON5 content may *not* | ||
work with existing JSON parsers. For this reason, JSON5 files use a new .json5 | ||
extension. *(TODO: new MIME type needed too.)* | ||
The code here is a **reference JavaScript implementation** for both Node.js | ||
and all browsers. It's based directly off of Douglas Crockford's own [JSON | ||
implementation][json_parse.js], and it's both robust and secure. | ||
## Why | ||
JSON isn't the friendliest to *write*. Keys need to be quoted, objects and | ||
arrays can't have trailing commas, and comments aren't allowed — even though | ||
none of these are the case with regular JavaScript today. | ||
That was fine when JSON's goal was to be a great data format, but JSON's usage | ||
has expanded beyond *machines*. JSON is now used for writing [configs][ex1], | ||
[manifests][ex2], even [tests][ex3] — all by *humans*. | ||
[ex1]: http://plovr.com/docs.html | ||
@@ -18,27 +38,25 @@ [ex2]: http://npmjs.org/doc/json.html | ||
**JSON5 is a proposed extension to JSON** that brings ES5 enhancements to its | ||
syntax. It remains a **strict subset of JavaScript**, adds **no new data | ||
types**, and is a **strict superset of existing JSON**. | ||
There are other formats that are human-friendlier, like YAML, but changing | ||
from JSON to a completely different format is undesirable in many cases. | ||
JSON5’s aim is to remain close to JSON and JavaScript. | ||
JSON5 is not an official successor to JSON, and existing JSON parsers may not | ||
understand these new features. It's thus recommended that files use a new | ||
extension like `.json5` to be explicit. *[TODO: New MIME type too?]* | ||
This module provides a JavaScript implementation that works on all modern JS | ||
engines (even IE6). Its parser is based directly off of Douglas Crockford's | ||
eval-free [json_parse.js][], making it both secure and robust. Give it a try! | ||
## Features | ||
These are the new features of JSON5's syntax. **All of these are optional**, | ||
and **all of these are part of ES5 JavaScript**. | ||
The following is the exact list of additions to JSON's syntax introduced by | ||
JSON5. **All of these are optional**, and **all of these come from ES5**. | ||
### Objects | ||
- Object keys can be unquoted if they're valid [identifiers]( | ||
https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Core_Language_Features#Variables). Yes, even reserved keywords are valid unquoted keys in ES5 [[§11.1.5](http://es5.github.com/#x11.1.5), [§7.6](http://es5.github.com/#x7.6)]. | ||
*[TODO: Unicode characters and escape sequences aren't yet supported in this implementation.]* | ||
- Object keys can be unquoted if they're valid [identifiers][mdn_variables]. | ||
Yes, even reserved keywords (like `default`) are valid unquoted keys in ES5 | ||
[[§11.1.5](http://es5.github.com/#x11.1.5), [§7.6](http://es5.github.com/#x7.6)]. | ||
*(TODO: Unicode characters and escape sequences aren’t yet supported in this | ||
implementation.)* | ||
- Objects can have trailing commas. | ||
[mdn_variables]: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Core_Language_Features#Variables | ||
### Arrays | ||
@@ -57,4 +75,4 @@ | ||
- Numbers can be hexadecimal (base 16). (Note that signed hexadecimals are not | ||
allowed by ES5, nor are hexadecimal floats.) | ||
- Numbers can be hexadecimal (base 16). (But note that neither signed | ||
hexadecimals nor hexadecimal floats are allowed by ES5.) | ||
@@ -65,3 +83,3 @@ - Numbers can begin or end with a (leading or trailing) decimal point. | ||
- Numbers can begin with an explicit plus (`+`) sign. | ||
- Numbers can begin with an explicit plus sign. | ||
@@ -72,4 +90,7 @@ ### Comments | ||
## Example | ||
The following is a contrived example, but it illustrates most of the features: | ||
```js | ||
@@ -103,7 +124,58 @@ { | ||
## Installation | ||
This implementation's own [package.json5](package.json5) is more realistic: | ||
Via npm on Node: | ||
```js | ||
// This file is written in JSON5 syntax, naturally, but npm needs a regular | ||
// JSON file, so compile via `npm run build`. Be sure to keep both in sync! | ||
{ | ||
name: 'json5', | ||
version: '0.2.0', | ||
description: 'JSON for the ES5 era.', | ||
keywords: ['json', 'es5'], | ||
author: 'Aseem Kishore <aseem.kishore@gmail.com>', | ||
contributors: [ | ||
'Max Nanasy <max.nanasy@gmail.com>', | ||
], | ||
main: 'lib/json5.js', | ||
bin: 'lib/cli.js', | ||
dependencies: {}, | ||
devDependencies: { | ||
mocha: '~1.0.3', | ||
}, | ||
scripts: { | ||
build: './lib/cli.js -c package.json5', | ||
test: 'mocha --ui exports --reporter spec', | ||
}, | ||
homepage: 'http://json5.org/', | ||
repository: { | ||
type: 'git', | ||
url: 'https://github.com/aseemk/json5.git', | ||
}, | ||
} | ||
``` | ||
## Community | ||
Join the [Google Group](http://groups.google.com/group/json5) if you're | ||
interested in JSON5 news, updates, and general discussion. | ||
Don't worry, it's very low-traffic. | ||
The [GitHub wiki](https://github.com/aseemk/json5/wiki) is a good place to track | ||
JSON5 support and usage. Contribute freely there! | ||
[GitHub Issues](https://github.com/aseemk/json5/issues) is the place to | ||
formally propose feature requests and report bugs. Questions and general | ||
feedback are better directed at the Google Group. | ||
## Usage | ||
This JavaScript implementation of JSON5 simply provides a `JSON5` object just | ||
like the native ES5 `JSON` object. | ||
To use from Node: | ||
``` | ||
npm install json5 | ||
@@ -116,9 +188,9 @@ ``` | ||
Or in the browser (adds the `JSON5` object to the global namespace): | ||
To use in the browser (adds the `JSON5` object to the global namespace): | ||
```html | ||
``` | ||
<script src="json5.js"></script> | ||
``` | ||
## Usage | ||
Then in both cases, you can simply replace native `JSON` calls with `JSON5`: | ||
@@ -130,8 +202,20 @@ ```js | ||
`JSON5.stringify()` is currently aliased to the native `JSON.stringify()` in | ||
order for the output to be fully compatible with all JSON parsers today. | ||
`JSON5.parse` supports all of the JSON5 features listed above (*TODO: except | ||
Unicode*), as well as the native [`reviver` argument][json-parse]. | ||
If you're running Node, you can also register a JSON5 `require()` hook to let | ||
you `require()` `.json5` files just like you can `.json` files: | ||
[json-parse]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse | ||
`JSON5.stringify` mainly avoids quoting keys where possible, but we hope to | ||
keep expanding it in the future (e.g. to also output trailing commas). | ||
It supports the native [`replacer` and `space` arguments][json-stringify], | ||
as well. *(TODO: Any implemented `toJSON` methods aren't used today.)* | ||
[json-stringify]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify | ||
### Extras | ||
If you're running this on Node, you can also register a JSON5 `require()` hook | ||
to let you `require()` `.json5` files just like you can `.json` files: | ||
```js | ||
@@ -144,3 +228,3 @@ require('json5/lib/require'); | ||
This module also provides a `json5` executable (requires Node) for converting | ||
JSON5 files to sibling JSON files: | ||
JSON5 files to JSON: | ||
@@ -151,2 +235,3 @@ ``` | ||
## Development | ||
@@ -166,5 +251,6 @@ | ||
[pull requests](https://github.com/aseemk/json5/pulls) — contributions are | ||
welcome. If you do submit a pull request, please be sure to add or update | ||
corresponding test cases, and ensure that `npm test` continues to pass. | ||
welcome. If you do submit a pull request, please be sure to add or update the | ||
tests, and ensure that `npm test` continues to pass. | ||
## License | ||
@@ -175,2 +261,3 @@ | ||
## Credits | ||
@@ -194,1 +281,3 @@ | ||
supporter, contributing multiple patches and ideas. Thanks Max! | ||
[Andrew Eisenberg](https://github.com/aeisenberg) has contributed the `stringify` method. |
@@ -48,4 +48,11 @@ // parse.js | ||
'Test case bug: expected JSON parsing to fail.'); | ||
assert.deepEqual(parseJSON5(), parseES5(), | ||
// Need special case for NaN as NaN != NaN | ||
if ( fileName === 'nan.json5' ) { | ||
assert.equal( isNaN( parseJSON5() ), isNaN( parseES5() ), | ||
'Expected parsed JSON5 to equal parsed ES5.'); | ||
} | ||
else { | ||
assert.deepEqual( parseJSON5(), parseES5(), | ||
'Expected parsed JSON5 to equal parsed ES5.'); | ||
} | ||
break; | ||
@@ -52,0 +59,0 @@ case '.js': |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
69300
79.01%141
9.3%1284
119.11%272
48.63%