Fixed #906: Implemented turning Python objects containing `True`, `False` and `None` into valid JSON using repair

This commit is contained in:
jos 2020-02-15 20:21:38 +01:00
parent 21aa049588
commit dcc66d5d81
3 changed files with 49 additions and 20 deletions

View File

@ -3,6 +3,12 @@
https://github.com/josdejong/jsoneditor https://github.com/josdejong/jsoneditor
## not yet published, version 8.6.0
- Fixed #906: Implemented turning Python objects containing `True`, `False`
and `None` into valid JSON using repair.
## 2020-02-06, version 8.5.3 ## 2020-02-06, version 8.5.3
- Fix #892: the undo/redo buttons in mode `code` being broken when custom - Fix #892: the undo/redo buttons in mode `code` being broken when custom

View File

@ -67,6 +67,12 @@ export function repair (jsString) {
const graveAccent = '\u0060' const graveAccent = '\u0060'
const acuteAccent = '\u00B4' const acuteAccent = '\u00B4'
const pythonConstants = {
None: 'null',
True: 'true',
False: 'false'
}
// helper functions to get the current/prev/next character // helper functions to get the current/prev/next character
function curr () { return jsString.charAt(i) } function curr () { return jsString.charAt(i) }
function next () { return jsString.charAt(i + 1) } function next () { return jsString.charAt(i + 1) }
@ -180,29 +186,29 @@ export function repair (jsString) {
} }
} }
function parseMongoDataType () { function parseValue () {
let c = curr() let c = curr()
let value let value = ''
let dataType = '' while (/\w/.test(c)) {
while (/[a-zA-Z_$]/.test(c)) { value += c
dataType += c
i++ i++
c = curr() c = curr()
} }
if (dataType.length > 0 && c === '(') { if (value.length > 0 && c === '(') {
// This is an MongoDB data type like {"_id": ObjectId("123")} // This is an MongoDB data type like in {"_id": ObjectId("123")}
let innerValue
i++ i++
c = curr() c = curr()
if (c === '"') { if (c === '"') {
// a data type containing a string, like ISODate("2012-12-19T06:01:17.171Z") // a data type containing a string, like ISODate("2012-12-19T06:01:17.171Z")
value = parseString(c) innerValue = parseString(c)
c = curr() c = curr()
} else { } else {
// a data type containing a value, like 'NumberLong(2)' // a data type containing a value, like 'NumberLong(2)'
value = '' innerValue = ''
while (c !== ')' && c !== '') { while (c !== ')' && c !== '') {
value += c innerValue += c
i++ i++
c = curr() c = curr()
} }
@ -213,14 +219,17 @@ export function repair (jsString) {
i++ i++
// return the value (strip the data type object) // return the value (strip the data type object)
return value return innerValue
} else { } else {
// huh? that's unexpected. don't touch it // huh? that's unexpected. don't touch it
return dataType + '(' + value + c return value + '(' + innerValue + c
} }
} else if (typeof pythonConstants[value] === 'string') {
// it's a python constant like None
return pythonConstants[value]
} else { } else {
// hm, no Mongo data type after all // just leave as is
return dataType return value
} }
} }
@ -260,15 +269,13 @@ export function repair (jsString) {
} else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) { } else if (/[a-zA-Z_$]/.test(c) && ['{', ','].indexOf(lastNonWhitespace()) !== -1) {
// an unquoted object key (like a in '{a:2}') // an unquoted object key (like a in '{a:2}')
chars.push(parseKey()) chars.push(parseKey())
} else { } else if (/\w/.test(c)) {
if (/[a-zA-Z_$]/.test(c)) { chars.push(parseValue())
chars.push(parseMongoDataType())
} else { } else {
chars.push(c) chars.push(c)
i++ i++
} }
} }
}
return chars.join('') return chars.join('')
} }

View File

@ -135,6 +135,22 @@ describe('util', () => {
assert.strictEqual(repair(mongoDocument), expectedJson) assert.strictEqual(repair(mongoDocument), expectedJson)
}) })
it('should replace Python constants None, True, False', () => {
const pythonDocument = '{\n' +
' "null": None,\n' +
' "true": True,\n' +
' "false": False\n' +
'}'
const expectedJson = '{\n' +
' "null": null,\n' +
' "true": true,\n' +
' "false": false\n' +
'}'
assert.strictEqual(repair(pythonDocument), expectedJson)
})
}) })
describe('jsonPath', () => { describe('jsonPath', () => {