找回密码
 立即注册
首页 业界区 业界 实现 json path 来评估函数式解析器的损耗 ...

实现 json path 来评估函数式解析器的损耗

第璋胁 2025-11-5 17:50:01
目的

之前就考虑评估过 函数式解析器 在dotnet这些面向对象语言上有着一些损耗,虽然表意性很强,与ABNF范式结合使用,维护性大大提升
不过由于性能考虑(以及之前认为也或许没有太多机会实现解析器),就没打算继续深究
不过现实确实有多次需要实现解析器,每次从0手写,太费时间了,比较很多实现对于解析性能并不需极致性能,(特别现在ai code疯狂的时代,老板哪会给那么多时间让你慢慢扣性能,老板们都常说ai几秒钟的事情,你个辣鸡还花几天)
所以为了血压和身体健康,只要性能将就,还是对于解析不太在意性能的场景以后就这样偷懒吧 (比如今年搞得 VKProxy 里面得动态条件和简单模板替换, 路子可行也许后面还是换掉吧,维护多累呀)
当然也有高手搞过类似的库,比如 Parlot , 不过其不支持 stream, 理想情况还是想stream 也能支持, 所以现在先简单搞一波:参考 Parlot  简单实现 string 解析器底层以及 json path 简单版
然后和 Newtonsoft.json 在简单的json path 场景比较,如果打不过,那怕没有继续的必要了
简要说明函数式解析器

这里以最简单 json path  "$.Name" 举例,
我们所需要解析即为 $ 开头, . 之后字符为属性名

换成代码大致为  Parser = Char('$').And(Char('.')).And(AnyExclude("[]().,\" '\r\n@$!= new WildcardSelectorStatment()).Name(nameof(WildcardSelector));    public static readonly Parser IndexSelector = Int.Then(static x => new IndexSelectorStatment() { Index = x }).Name(nameof(IndexSelector));    public static readonly Parser StringLiteral = Between(DoubleQuoted, ZeroOrOne(Any("\"", mustHasEnd: true, escape: '\\')), DoubleQuoted).Or(Between(SingleQuoted, ZeroOrOne(Any("'", mustHasEnd: true, escape: '\\')), SingleQuoted)).Name(nameof(StringLiteral));    public static readonly Parser NameSelector = StringLiteral.Then(static x => new Member() { Name = x.Span.ToString() }).Name(nameof(NameSelector));    public static readonly Parser Start = Int;    public static readonly Parser End = Int;    public static readonly Parser Step = Int;    public static readonly Parser S = IgnoreChar(new char[]    { (char)0x20, // Space      (char)0x09, //Horizontal tab      (char)0x0A, // Line feed or New line      (char)0x0D // Carriage return    }).Name(nameof(S));    public static readonly Parser CurrentNodeIdentifier = Char('@').Name(nameof(CurrentNodeIdentifier));    public static readonly Parser LogicalNotOp = Char('!').Name(nameof(LogicalNotOp));    public static readonly Parser ComparisonOp = Text("==").Or(Text("!=")).Or(Text("=")).Or(Text("")).Name(nameof(ComparisonOp));    public static readonly Parser Num = Decimal(NumberOptions.Float).Then(static x => new NumberValue(x)).Name(nameof(Num));    public static readonly Parser True = Text("true").Then(static x => BoolValue.True).Name(nameof(True));    public static readonly Parser False = Text("false").Then(static x => BoolValue.False).Name(nameof(False));    public static readonly Parser Null = Text("null").Then(static x => NullValue.Value).Name(nameof(Null));    private const string name = "[]().,\" '\r\n@$!=

相关推荐

您需要登录后才可以回帖 登录 | 立即注册