解析不完整的'json'字符串,输出完整的json

使用场景:

1、数字超过32位数时,显示科学数字

2、面对不完整的json字符串,如:缺少闭合符号

 

代码如下:

复制代码
export default function fakeParseJSON(jsonStr) {
    const str = jsonStr.replace(/[\r\n]/g, '').replace(/\ +/g, '').replace(/'/g, '"')
    let i = 0
    return parseValue()

    function parseValue() {
        skipWhitespace()
        if (i >= str.length) {
            return null
        }
        const value =
        parseString() ??
        parseNumber() ??
        parseObject() ??
        parseArray() ??
        parseKeyword('true', true) ??
        parseKeyword('false', false) ??
        parseKeyword('null', null)
        skipWhitespace()
        return value
    }

    function parseObject() {
        if (str[i] === '{') {
            i++
            // skipWhitespace()

            const result = {}

            let initial = true
            // if it is not '}',
            // we take the path of string -> whitespace -> ':' -> value -> ...
            while (str[i] !== '}' && i < str.length) {
                if (!initial) {
                    eatComma()
                    // skipWhitespace()
                }
                const key = parseString()
                // skipWhitespace()
                eatColon()
                const value = parseValue()
                if (key !== undefined) {
                    result[key] = value
                }
                initial = false
            }
            // move to the next character of '}'
            i++

            return result
        }
    }

    function parseArray() {
        if (str[i] === '[') {
            i++
            // skipWhitespace()

            const result = []
            let initial = true
            while (str[i] !== ']' && i < str.length) {
                if (!initial) {
                eatComma()
                }
                const value = parseValue()
                result.push(value)
                initial = false
            }
            // move to the next character of ']'
            i++
            return result
        }
    }

    function parseKeyword(name, value) {
        if (str.slice(i, i + name.length) === name) {
            i += name.length
            return value
        }
    }

    function skipWhitespace() {
        while (
        str[i] === ' ' ||
        str[i] === '\n' ||
        str[i] === '\t' ||
        str[i] === '\r'
        ) {
            i++
        }
    }

    function parseString() {
        if (str[i] === '"') {
            i++
            let result = ''
            while (str[i] && str[i] !== '"') {
                if (str[i] === '\\') {
                    const char = str[i + 1]
                    if (
                        char === '"' ||
                        char === '\\' ||
                        char === '/' ||
                        char === 'b' ||
                        char === 'f' ||
                        char === 'n' ||
                        char === 'r' ||
                        char === 't'
                    ) {
                        result += char
                        i++
                    } else if (char === 'u') {
                        if (
                        isHexadecimal(str[i + 2]) &&
                        isHexadecimal(str[i + 3]) &&
                        isHexadecimal(str[i + 4]) &&
                        isHexadecimal(str[i + 5])
                        ) {
                            // Unicode 编码 转成 字符
                            result += String.fromCharCode(
                                parseInt(str.slice(i + 2, i + 6), 16)
                            )
                            i += 5
                        }
                    }
                } else {
                    result += str[i]
                }
                i++
            }
            i++
            return result
        }
    }

    function isHexadecimal(char) {
        return (
        (char >= '0' && char <= '9') ||
        (char.toLowerCase() >= 'a' && char.toLowerCase() <= 'f')
        )
    }

    function parseNumber() {
        const start = i
        if (str[i] === '-') {
            i++
        }
        if (str[i] === '0') {
            i++
        } else if (str[i] >= '1' && str[i] <= '9') {
            i++
            while (str[i] >= '0' && str[i] <= '9') {
                i++
            }
        }

        if (str[i] === '.') {
            i++
            while (str[i] >= '0' && str[i] <= '9') {
                i++
            }
        }
        if (str[i] === 'e' || str[i] === 'E') {
            i++
            if (str[i] === '-' || str[i] === '+') {
                i++
            }
            while (str[i] >= '0' && str[i] <= '9') {
                i++
            }
        }
        if (i > start) {
            return Number(str.slice(start, i))
        }
    }

    function eatComma() {
        if (str[i] !== ',') {
            throw new Error('Expected ",".')
        }
        i++
    }

    function eatColon() {
        if (str[i] !== ':' && i < str.length) {
            throw new Error('Expected ":".')
        }
        i++
    }
}
复制代码

 

posted @   ^柒  阅读(61)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示