如何手写实现 JSON Parser

简介: 【11月更文挑战第10天】本文介绍了如何使用 Python 手写实现一个简单的 JSON 解析器。通过逐字符读取 JSON 字符串,解析出对象、数组、字符串、数字、布尔值和 null 等基本数据结构。文章详细描述了每个步骤的具体实现方法,包括去除空白字符、解析基础数据类型、解析字符串、数组和对象,以及核心的 `parse_value` 函数。最后,提供了一个完整的 JSON 解析器主函数示例。

以下是一个使用 Python 语言手写实现一个简单 JSON Parser(解析器)的基本步骤示例,主要聚焦于解析基本的 JSON 数据结构,如对象、数组、字符串、数字、布尔值和 null 等。

整体思路


JSON 数据本质上是一种文本格式,我们的目标是读取这个文本,按照 JSON 的语法规则解析出相应的数据结构。实现的思路大致是通过逐字符读取输入的 JSON 字符串,根据不同的字符和语法规则来构建对应的 Python 数据结构(因为最终要把 JSON 解析成 Python 里能处理的数据形式)。

具体实现步骤


  1. 去除空白字符(可选)
    首先,可以编写一个函数来去除 JSON 字符串中多余的空白字符(空格、制表符、换行等),这不是必需的,但可以让后续解析过程更简洁。例如:


def remove_whitespace(json_str):
    return json_str.replace(" ", "").replace("\t", "").replace("\n", "")


  1. 解析基础数据类型(数字、布尔值、null)
    这些基础类型相对简单,可以通过识别特定的字符组合来进行解析。


  • 数字解析
    可以使用正则表达式或者通过判断字符是否是数字相关字符(0 - 9、小数点等)来解析数字。例如,简单的数字解析函数如下:


def parse_number(token):
    try:
        return float(token) if '.' in token else int(token)
    except ValueError:
        raise ValueError("Invalid number format")


  • 布尔值和 null 解析
    识别特定的字符串来判断,比如truefalsenull


def parse_literal(token):
    if token == "true":
        return True
    elif token == "false":
        return False
    elif token == "null":
        return None
    raise ValueError("Invalid literal")


  1. 解析字符串
    字符串在 JSON 中有特定的格式,是以双引号"开头和结尾,中间包含各种字符(需要对一些特殊字符进行转义处理)。以下是一个简单的字符串解析函数示例:


def parse_string(json_str):
    if json_str[0]!= '"':
        raise ValueError("Invalid string format")
    end_index = 1
    buffer = ""
    while end_index < len(json_str):
        if json_str[end_index] == '"':
            return buffer
        elif json_str[end_index] == '\\':
            end_index += 1
            if end_index < len(json_str):
                buffer += json_str[end_index]
        else:
            buffer += json_str[end_index]
        end_index += 1
    raise ValueError("Unclosed string")


  1. 解析数组
    数组是以方括号[开头,以]结尾,中间包含多个元素(元素可以是各种 JSON 数据类型),用逗号,分隔。实现解析数组的函数如下:


def parse_array(json_str):
    if json_str[0]!= '[':
        raise ValueError("Invalid array format")
    elements = []
    json_str = json_str[1:-1]  # 去除方括号
    i = 0
    while i < len(json_str):
        element, length = parse_value(json_str[i:])
        elements.append(element)
        i += length
        if i < len(json_str) and json_str[i] == ',':
            i += 1
    return elements


这里调用了一个parse_value函数,它会根据不同的起始字符判断要解析的是哪种数据类型,后续会定义这个函数。


  1. 解析对象
    对象是以花括号{开头,以}结尾,中间是键值对,键和值之间用冒号:分隔,键值对之间用逗号,分隔。解析对象的函数示例如下:


def parse_object(json_str):
    if json_str[0]!= '{':
        raise ValueError("Invalid object format")
    result = {}
    json_str = json_str[1:-1]  # 去除花括号
    i = 0
    while i < len(json_str):
        key = parse_string(json_str[i:])
        i += len(key) + 2  # 跳过键和后面的冒号
        value, length = parse_value(json_str[i:])
        result[key] = value
        i += length
        if i < len(json_str) and json_str[i] == ',':
            i += 1
    return result


同样,这里也依赖parse_value函数来解析对象中的值。


  1. 核心的parse_value函数
    这个函数根据传入的 JSON 字符串片段的第一个字符来判断要解析的数据类型,然后调用相应的解析函数:


def parse_value(json_str):
    if json_str[0] == '"':
        return parse_string(json_str), len(parse_string(json_str))
    elif json_str[0].isdigit() or json_str[0] == '-':
        num_end_index = 0
        while num_end_index < len(json_str) and (json_str[num_end_index].isdigit() or json_str[num_end_index] in ['.', '-']):
            num_end_index += 1
        return parse_number(json_str[:num_end_index]), num_end_index
    elif json_str[0] == '[':
        return parse_array(json_str), len(json_str)
    elif json_str[0] == '{':
        return parse_object(json_str), len(json_str)
    elif json_str[:4].lower() in ["true", "false", "null"]:
        return parse_literal(json_str[:4].lower()), 4
    raise ValueError("Invalid JSON value")


  1. 完整的 JSON 解析器主函数
    将上述函数整合起来,创建一个可以接收 JSON 字符串并返回解析后数据结构的主函数:


def json_parser(json_str):
    json_str = remove_whitespace(json_str)
    return parse_value(json_str)[0]


这样,通过调用json_parser函数,传入一个 JSON 字符串,就可以尝试解析并返回对应的 Python 数据结构了,例如:


json_data = '{"name": "John", "age": 30, "is_student": false}'
result = json_parser(json_data)
print(result)


请注意,这个手写的 JSON Parser 只是一个简单的示例,并没有涵盖 JSON 所有的复杂特性和严格的错误处理情况(比如处理 Unicode 字符更复杂的转义、严格的语法错误提示等),但可以作为理解 JSON 解析原理的一个基础实现。


如果要用其他编程语言,如 Java、JavaScript 等,思路类似,但代码实现细节会根据语言特性有所不同,比如在 Java 中要处理字符读取和字符串操作就需要借助不同的类和方法等。

相关文章
|
JSON IDE 测试技术
软件测试|好用的pycharm插件推荐(二)—— JSON Parser
软件测试|好用的pycharm插件推荐(二)—— JSON Parser
|
存储 JSON Java
Java - Jackson JSON Java Parser API
Java - Jackson JSON Java Parser API
153 0
|
JSON JavaScript 安全
使用安全json parser防止json注入
 今天在网上瞎逛又看到了一个不错的东西。 有些程序员如果没有很好的在javascript中解析json数据,往往会直接eval把json转成js对象,这时候如果json的数据中包含了被注入的恶意数据,则可能导致代码注入的问题。
1994 0
|
1月前
|
JSON API 数据格式
淘宝拍立淘按图搜索API系列,json数据返回
淘宝拍立淘按图搜索API系列通过图像识别技术实现商品搜索功能,调用后返回的JSON数据包含商品标题、图片链接、价格、销量、相似度评分等核心字段,支持分页和详细商品信息展示。以下是该API接口返回的JSON数据示例及详细解析:
|
1月前
|
JSON 算法 API
Python采集淘宝商品评论API接口及JSON数据返回全程指南
Python采集淘宝商品评论API接口及JSON数据返回全程指南
|
2月前
|
机器学习/深度学习 JSON 监控
淘宝拍立淘按图搜索与商品详情API的JSON数据返回详解
通过调用taobao.item.get接口,获取商品标题、价格、销量、SKU、图片、属性、促销信息等全量数据。
|
1月前
|
JSON API 数据安全/隐私保护
Python采集淘宝拍立淘按图搜索API接口及JSON数据返回全流程指南
通过以上流程,可实现淘宝拍立淘按图搜索的完整调用链路,并获取结构化的JSON商品数据,支撑电商比价、智能推荐等业务场景。
|
2月前
|
JSON 缓存 自然语言处理
多语言实时数据微店商品详情API:技术实现与JSON数据解析指南
通过以上技术实现与解析指南,开发者可高效构建支持多语言的实时商品详情系统,满足全球化电商场景需求。
|
2月前
|
JSON API 数据格式
干货满满!淘宝商品详情数据,淘宝API(json数据返回)
淘宝商品详情 API 接口(如 taobao.item.get)的 JSON 数据返回示例如下
|
1月前
|
JSON 中间件 Java
【GoGin】(3)Gin的数据渲染和中间件的使用:数据渲染、返回JSON、浅.JSON()源码、中间件、Next()方法
我们在正常注册中间件时,会打断原有的运行流程,但是你可以在中间件函数内部添加Next()方法,这样可以让原有的运行流程继续执行,当原有的运行流程结束后再回来执行中间件内部的内容。​ c.Writer.WriteHeaderNow()还会写入文本流中。可以看到使用next后,正常执行流程中并没有获得到中间件设置的值。接口还提供了一个可以修改ContentType的方法。判断了传入的状态码是否符合正确的状态码,并返回。在内部封装时,只是标注了不同的render类型。再看一下其他返回的类型;
158 3