简略粗犷,间接上代码,
会把{"a":1,"a":2}
解析成{"a":[1,2]}
附上npm链接:clarinet
var clarinet = require("clarinet");class InvalidJSON { result = {} /** * @description 进入的括号层数 */ bracketCount = 0 /** * @type { Array<{ type: 'array'; value: any[] } | { type: 'object'; arrayKeys: string[]; arrayKeysMap: { [key: string]: boolean; }; keys: string[]; value: { [key: string]: any } }> } */ queue = [] get lastQueue() { const queue = this.queue return queue[queue.length - 1] } queuePop() { this.queue.pop() this.bracketCount-- } queuePush(item) { this.queue.push(item) this.bracketCount++ } onopenobject(key) { // console.log('onopenobject', key) const value = {} this.bracketCount === 0 && (this.result = value) this.lastQueue && this.onvalue(value) this.queuePush({ keys: [key], arrayKeys: [], arrayKeysMap: {}, type: 'object', value }) } onkey(key) { // console.log('onkey', key) const { keys, type, arrayKeys } = this.lastQueue if (type !== 'object') { return } keys.includes(key) && arrayKeys.push(key) keys.push(key) } onvalue(v) { // console.log('onvalue', v) const { type, value, keys, arrayKeysMap, arrayKeys } = this.lastQueue if (type === 'array') { value.push(v) } else if (type === 'object') { const lastKeys = keys[keys.length - 1] if (arrayKeys.includes(lastKeys)) { if (!arrayKeysMap[lastKeys]) { arrayKeysMap[lastKeys] = true value[lastKeys] = [value[lastKeys]] } value[lastKeys].push(v) } else { value[lastKeys] = v } } } oncloseobject() { // console.log('onclosearray') this.queuePop() } onopenarray() { // console.log('onopenarray') const value = [] this.bracketCount === 0 && (result = value) this.lastQueue && this.onvalue(value) this.queuePush({ type: 'array', value }) } onclosearray() { // console.log('onclosearray') this.queuePop() } /** * @param { string } json 不非法的json */ parse(json) { this.bracketCount = 0 this.result = {} this.queue = [] this.parser.write(json).close() return this.result } parser constructor() { const parser = clarinet.parser() const parserEvents = ['value', 'openobject', 'key', 'closeobject', 'openarray', 'closearray'] parserEvents.forEach(event => { const eventName = `on${event}` parser[eventName] = (...args) => this[eventName](...args) }) this.parser = parser }}const invalidJSON = new InvalidJSON()console.log(JSON.stringify(invalidJSON.parse('{"p":7,"p": 9,"w":3,"q":[0,8],"g":77,"g":{"a":100,"d":{"z":2},"d":{"z":3}}}')))
原理:clarinet会解析json字符串,在每个json字符串关键点触发回调,
如开始一个object,进入一个key,进入一个value,开始一个array,
利用这些回调,拼装出冀望的格局