Implement support for repairing line separate JSON
This commit is contained in:
parent
0ba8321eb3
commit
fd0db5dc73
|
@ -5,6 +5,7 @@ https://github.com/josdejong/jsoneditor
|
||||||
## not yet published, version 8.6.4
|
## not yet published, version 8.6.4
|
||||||
|
|
||||||
- Fix #921: `sortObjectKeys` emits `onChange` events.
|
- Fix #921: `sortObjectKeys` emits `onChange` events.
|
||||||
|
- Implement support for repairing line separate JSON.
|
||||||
|
|
||||||
|
|
||||||
## 2020-03-18, version 8.6.3
|
## 2020-03-18, version 8.6.3
|
||||||
|
|
|
@ -41,6 +41,8 @@ export function repair (jsString) {
|
||||||
// escape all single and double quotes inside strings
|
// escape all single and double quotes inside strings
|
||||||
const chars = []
|
const chars = []
|
||||||
let i = 0
|
let i = 0
|
||||||
|
let indent = 0
|
||||||
|
let isLineSeparatedJson = false
|
||||||
|
|
||||||
// If JSON starts with a function (characters/digits/"_-"), remove this function.
|
// If JSON starts with a function (characters/digits/"_-"), remove this function.
|
||||||
// This is useful for "stripping" JSONP objects to become JSON
|
// This is useful for "stripping" JSONP objects to become JSON
|
||||||
|
@ -109,19 +111,37 @@ export function repair (jsString) {
|
||||||
|
|
||||||
// skip a block comment '/* ... */'
|
// skip a block comment '/* ... */'
|
||||||
function skipBlockComment () {
|
function skipBlockComment () {
|
||||||
i += 2
|
if (curr() === '/' && next() === '*') {
|
||||||
while (i < jsString.length && (curr() !== '*' || next() !== '/')) {
|
i += 2
|
||||||
i++
|
while (i < jsString.length && (curr() !== '*' || next() !== '/')) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
i += 2
|
||||||
|
|
||||||
|
if (curr() === '\n') {
|
||||||
|
i++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
i += 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip a comment '// ...'
|
// skip a comment '// ...'
|
||||||
function skipComment () {
|
function skipComment () {
|
||||||
i += 2
|
if (curr() === '/' && next() === '/') {
|
||||||
while (i < jsString.length && (curr() !== '\n')) {
|
i += 2
|
||||||
|
while (i < jsString.length && (curr() !== '\n')) {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseWhiteSpace () {
|
||||||
|
let whitespace = ''
|
||||||
|
while (i < jsString.length && isWhiteSpace(curr())) {
|
||||||
|
whitespace += curr()
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return whitespace
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -245,13 +265,19 @@ export function repair (jsString) {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (i < jsString.length) {
|
while (i < jsString.length) {
|
||||||
|
skipBlockComment()
|
||||||
|
skipComment()
|
||||||
|
|
||||||
const c = curr()
|
const c = curr()
|
||||||
|
|
||||||
if (c === '/' && next() === '*') {
|
if (c === '{') {
|
||||||
skipBlockComment()
|
indent++
|
||||||
} else if (c === '/' && next() === '/') {
|
}
|
||||||
skipComment()
|
if (c === '}') {
|
||||||
} else if (isSpecialWhiteSpace(c)) {
|
indent--
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSpecialWhiteSpace(c)) {
|
||||||
// special white spaces (like non breaking space)
|
// special white spaces (like non breaking space)
|
||||||
chars.push(' ')
|
chars.push(' ')
|
||||||
i++
|
i++
|
||||||
|
@ -265,6 +291,21 @@ export function repair (jsString) {
|
||||||
chars.push(parseString(quoteRight))
|
chars.push(parseString(quoteRight))
|
||||||
} else if (c === quoteDblLeft) {
|
} else if (c === quoteDblLeft) {
|
||||||
chars.push(parseString(quoteDblRight))
|
chars.push(parseString(quoteDblRight))
|
||||||
|
} else if (c === '}') {
|
||||||
|
// check for missing comma between objects
|
||||||
|
chars.push(c)
|
||||||
|
i++
|
||||||
|
|
||||||
|
const whitespaces = parseWhiteSpace()
|
||||||
|
skipBlockComment()
|
||||||
|
|
||||||
|
if (curr() === '{' || nextNonWhiteSpace() === '{') {
|
||||||
|
chars.push(',')
|
||||||
|
if (indent === 0) {
|
||||||
|
isLineSeparatedJson = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chars.push(whitespaces)
|
||||||
} else if (c === ',' && [']', '}'].indexOf(nextNonWhiteSpace()) !== -1) {
|
} else if (c === ',' && [']', '}'].indexOf(nextNonWhiteSpace()) !== -1) {
|
||||||
// skip trailing commas
|
// skip trailing commas
|
||||||
i++
|
i++
|
||||||
|
@ -280,6 +321,11 @@ export function repair (jsString) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isLineSeparatedJson) {
|
||||||
|
chars.unshift('[\n')
|
||||||
|
chars.push('\n]')
|
||||||
|
}
|
||||||
|
|
||||||
return chars.join('')
|
return chars.join('')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,28 @@ describe('util', () => {
|
||||||
|
|
||||||
assert.strictEqual(repair(pythonDocument), expectedJson)
|
assert.strictEqual(repair(pythonDocument), expectedJson)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should repair missing comma between objects', () => {
|
||||||
|
const text = '{"aray": [{}{}]}'
|
||||||
|
const expected = '{"aray": [{},{}]}'
|
||||||
|
|
||||||
|
assert.strictEqual(repair(text), expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should repair line separated json (for example from robo3t', () => {
|
||||||
|
const text = '' +
|
||||||
|
'/* 1 */\n' +
|
||||||
|
'{}\n' +
|
||||||
|
'\n' +
|
||||||
|
'/* 2 */\n' +
|
||||||
|
'{}\n' +
|
||||||
|
'\n' +
|
||||||
|
'/* 3 */\n' +
|
||||||
|
'{}\n'
|
||||||
|
const expected = '[\n{},\n\n{},\n\n{}\n\n]'
|
||||||
|
|
||||||
|
assert.strictEqual(repair(text), expected)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('jsonPath', () => {
|
describe('jsonPath', () => {
|
||||||
|
|
Loading…
Reference in New Issue