Python中是否存在解析特定格式序列化对象的可用库?
解析自定义结构化输入的Python实现
我之前也碰到过类似的需求——这种自定义的序列化对象语法确实没有现成的解析库直接适配,不过用Python的pyparsing库来实现完全可行,而且灵活性很高,能轻松扩展更多类型。
核心思路
我们需要分步骤定义语法规则,然后给每个规则绑定解析动作,把原始的字符串转换成你需要的字典/列表结构:
- 先处理最基础的类型:整数、浮点数、布尔值、字符串
- 再处理数组:数组元素可以是任意基础类型、结构体或其他数组
- 最后处理结构体:结构体由类型名+括号包裹的参数列表组成,参数可以是任意合法元素
完整代码实现
首先得安装pyparsing:
pip install pyparsing
然后是解析代码:
from pyparsing import ( Word, nums, alphas, Combine, Optional, Literal, QuotedString, Group, Forward, ZeroOrMore, oneOf ) # 1. 定义基础类型的语法规则 # 匹配整数和浮点数(支持负号) number = Combine(Optional('-') + Word(nums) + Optional('.' + Word(nums))) # 匹配布尔值true/false boolean = oneOf("true false").setParseAction(lambda tokens: tokens[0] == "true") # 匹配双引号包裹的字符串 string = QuotedString('"') # 2. 定义数组的语法规则(递归支持嵌套数组) array = Forward() # 数组元素可以是任意合法类型 array_element = number | boolean | string | Forward() array << Literal('[') + Group(ZeroOrMore(array_element + Optional(','))) + Literal(']') # 将数组解析成Python列表 array.setParseAction(lambda tokens: [t for t in tokens[1]]) # 3. 定义结构体的语法规则(递归支持嵌套结构体) struct = Forward() # 结构体参数可以是任意合法类型 struct_arg = number | boolean | string | array | struct struct << Word(alphas + nums) + Literal('(') + Group(ZeroOrMore(struct_arg + Optional(','))) + Literal(')') # 将结构体解析成指定格式的字典 struct.setParseAction(lambda tokens: { "type": tokens[0], "args": [ # 把字符串类型的数字转成数值类型 float(t) if '.' in t else int(t) if isinstance(t, str) else t for t in tokens[2] ] }) # 顶层表达式:可以是结构体、数组或任意基础类型 top_expr = struct | array | number | boolean | string # 测试你的示例输入 input_str = 'Struct(1.5, false, Struct2("text"), [1, 2, 3])' parsed_result = top_expr.parseString(input_str, parseAll=True)[0] # 输出格式化后的结果 import json print(json.dumps(parsed_result, indent=2))
安全优化建议
上面的代码里直接用了类型转换来处理数字,如果你担心输入中存在恶意内容(虽然你的场景应该是可控的),可以把数字的解析动作改成更安全的自定义函数,避免潜在风险:
def safe_convert_number(token): s = token[0] try: return int(s) except ValueError: return float(s) # 给number绑定安全转换动作 number.setParseAction(safe_convert_number)
测试效果
运行代码后,你的示例输入会输出:
{ "type": "Struct", "args": [ 1.5, false, { "type": "Struct2", "args": [ "text" ] }, [ 1, 2, 3 ] ] }
完全符合你的期望输出。
内容的提问来源于stack exchange,提问作者Demetroid
相关产品推荐
相关产品推荐

