如何实现一个JSON.parse

之前收藏的一个把 json字符串转对象的解析器,代码比较易懂,直接贴源码。对于刚接触这块的同学应该能起到入门的作用
var json = {}

json.parse = function(text) {
    var at = 0
    var ch = ' '

    var escapee = {
        '"': '"',
        '\\': '\\',
        '/': '/',
        b: '\b',
        f: '\f',
        n: '\n',
        r: '\r',
        t: '\t'
    }

    var error = function(m) {
        console.log(m);
        throw {
            name: 'SyntaxError',
            message: m,
            at: at,
            text: text
        }
    }

    var next = function(c) {
        if (c && c !== ch) {
            error("Expected '" + c + "' instead of '" + ch + "'")
        }
        ch = text.charAt(at)
        at = at + 1

        return ch
    }

    var white = function() {
        while (ch && ch <= ' ') {
            next()
        }
    }

    var number = function() {
        var number
        var string = ''

        if (ch === '-') {
            string = '-'
            next('-')
        }

        while (ch >= '0' && ch <= '9') {
            string += ch
            next()
        }

        if (ch === '.') {
            string += '.'
            while (next() && ch >= '0' && ch <= 9) {
                string += ch
            }
        }

        if (ch === 'e' || ch === 'E') {
            string += ch
            next()
            if (ch === '-' || ch === '+') {
                string += ch
                next()
            }
            while (ch >= '0' && ch <= '9') {
                string += ch
                next()
            }
        }

        number = string - 0
        if (!isFinite(number)) {
            error('Bad number')
        } else {
            return number
        }
    }

    var string = function() {
        var hex
        var i
        var string = ''
        var uffff

        if (ch === '"') {
            while (next()) {
                if (ch === '"') {
                    next()
                    return string // 空字符串
                }

                if (ch === '\\') {
                    next()
                    if (ch === 'u') {
                        uffff = 0
                        for (var i = 0; i < 4; i += 1) {
                            hex = parseInt(next(), 16)
                            if (!isFinite(hex)) {
                                break
                            }

                            uffff = uffff * 16 + hex
                        }
                        string += String.fromCharCode(uffff)
                    } else if (typeof escapee[ch] === 'string') {
                        string += escapee[ch]
                    } else {
                        break
                    }
                } else {
                    string += ch
                }
            }
        }
        error('Bad string')
    }

    var word = function() {
        switch (ch) {
            case 't':
                next('t');
                next('r');
                next('u');
                next('e');
                return true;
            case 'f':
                next('f');
                next('a');
                next('l');
                next('s');
                next('e');
                return false;
            case 'n':
                next('n');
                next('u');
                next('l');
                next('l');
                return null;
        }

        error("Unexpected '" + ch + "'");
    }
    var value

    var array = function() {
        var array = []
        if (ch === '[') {
            next('[')
            white()

            if (ch === ']') {
                next(']')
                return array // 空数组
            }

            while (ch) {
                array.push(value())
                white()
                if (ch === ']') {
                    next(']')
                    return array
                }
                next(',')
                white()
            }
        }

        error('Bad array')
    }

    var object = function() {
        var key
        var object = {}
        if (ch === '{') {
            next('{')
            white()

            if (ch === '}') {
                next('}')
                return object // 空对象
            }

            while (ch) {
                key = string()
                white()
                next(':')

                if (Object.hasOwnProperty.call(object, key)) {
                    error('Duplicate key "' + key + '"');
                }

                object[key] = value()
                white()
                if (ch === '}') {
                    next('}')
                    return object
                }
                next(',')
                white()
            }
        }

        error('Bad object')
    }

    value = function() {
        white()
        switch (ch) {
            case '{':
                return object()
            case '[':
                return array()
            case '"':
                return string()
            case '-':
                return number()
            default:
                return ch >= '0' && ch <= '9' ? number() : word()
        }
    }

    return value(text)
}

实现思路

json的结构分析

json的结构包含几种元素:

object(name value pair object)

此处指狭义的对象,名值对形式。广义上任何元素都是对象。

array

由[]符号包裹,元素用英文逗号分隔。

字面类型

字面类型最为简单,不能再嵌套

number

boolean

true or false

null

下面放几张json.org的图,以直观的形式展示json格式。

clipboard.png

clipboard.png

clipboard.png

object 内部的value和array内部的元素都可以是任意组成类型,可以存在任意层次的嵌套。因此用递归方式解析比较简单。

你可能感兴趣的:(解析器,解析,算法)