From 6551701153f1ca2f355bb6c53553c1608e2dd159 Mon Sep 17 00:00:00 2001 From: jos Date: Thu, 6 Dec 2018 20:15:14 +0100 Subject: [PATCH] Fixed #610: JSON Repair now removes trailing commas --- HISTORY.md | 1 + src/js/util.js | 22 ++++++++++++++++++++-- test/util.test.js | 14 +++++++++++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 3d491b5..1a524f2 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,6 +5,7 @@ https://github.com/josdejong/jsoneditor ## not yet released, version 5.26.3 +- Fixed #610: JSON Repair now removes trailing commas. - Upgraded devDependency `gulp` to v4. Thanks @maestr0. diff --git a/src/js/util.js b/src/js/util.js index bae03ee..b852377 100644 --- a/src/js/util.js +++ b/src/js/util.js @@ -65,13 +65,17 @@ exports.sanitize = function (jsString) { function next() { return jsString.charAt(i + 1); } function prev() { return jsString.charAt(i - 1); } + function isWhiteSpace(c) { + return c === ' ' || c === '\n' || c === '\r' || c === '\t'; + } + // get the last parsed non-whitespace character function lastNonWhitespace () { var p = chars.length - 1; while (p >= 0) { var pp = chars[p]; - if (pp !== ' ' && pp !== '\n' && pp !== '\r' && pp !== '\t') { // non whitespace + if (!isWhiteSpace(pp)) { return pp; } p--; @@ -80,6 +84,16 @@ exports.sanitize = function (jsString) { return ''; } + // get at the first next non-white space character + function nextNonWhiteSpace() { + var iNext = i + 1; + while (iNext < jsString.length && isWhiteSpace(jsString[iNext])) { + iNext++; + } + + return jsString[iNext]; + } + // skip a block comment '/* ... */' function skipBlockComment () { i += 2; @@ -166,7 +180,7 @@ exports.sanitize = function (jsString) { } else if (c === '\u00A0' || (c >= '\u2000' && c <= '\u200A') || c === '\u202F' || c === '\u205F' || c === '\u3000') { // special white spaces (like non breaking space) - chars.push(' ') + chars.push(' '); i++ } else if (c === quote) { @@ -184,6 +198,10 @@ exports.sanitize = function (jsString) { else if (c === quoteDblLeft) { parseString(quoteDblRight); } + else if (c === ',' && [']', '}'].indexOf(nextNonWhiteSpace()) !== -1) { + // skip trailing commas + i++; + } else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) { // an unquoted object key (like a in '{a:2}') parseKey(); diff --git a/test/util.test.js b/test/util.test.js index 194da7d..39103c7 100644 --- a/test/util.test.js +++ b/test/util.test.js @@ -50,7 +50,7 @@ describe('util', function () { assert.equal(util.sanitize('\u2018foo\u2019'), '"foo"') assert.equal(util.sanitize('\u201Cfoo\u201D'), '"foo"') assert.equal(util.sanitize('\u0060foo\u00B4'), '"foo"') - }) + }); it('remove comments', function () { assert.equal(util.sanitize('/* foo */ {}'), ' {}'); @@ -84,6 +84,18 @@ describe('util', function () { assert.equal(util.sanitize('callback({}'), 'callback({}'); }); + it('should strip trailing zeros', function () { + // matching + assert.equal(util.sanitize('[1,2,3,]'), '[1,2,3]'); + assert.equal(util.sanitize('[1,2,3,\n]'), '[1,2,3\n]'); + assert.equal(util.sanitize('[1,2,3, \n ]'), '[1,2,3 \n ]'); + assert.equal(util.sanitize('{"a":2,}'), '{"a":2}'); + + // not matching + assert.equal(util.sanitize('"[1,2,3,]"'), '"[1,2,3,]"'); + assert.equal(util.sanitize('"{a:2,}"'), '"{a:2,}"'); + }); + }); describe('jsonPath', function () {