【问题标题】:Why do divisions not work in jsonpath-ng?为什么除法在 jsonpath-ng 中不起作用?
【发布时间】:2021-05-20 09:28:22
【问题描述】:

Jsonpath-ng 提供如下基本算术:

from jsonpath_ng import jsonpath
from jsonpath_ng.ext import parse

jsonpath_expr = parse('$.foo * 2')
target = {'foo': 2}
result = jsonpath_expr.find(target)
result = [match.value for match in result]
print(result)

结果:[4]

但是,如果我将表达式更改为 $.foo / 2,则会收到解析错误:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    jsonpath_expr = parse('$.foo / 2')
  File "C:\Users\micha\AppData\Roaming\Python\Python38\site-packages\jsonpath_ng\ext\parser.py", line 172, in parse
    return ExtentedJsonPathParser(debug=debug).parse(path)
  File "C:\Users\micha\AppData\Roaming\Python\Python38\site-packages\jsonpath_ng\parser.py", line 32, in parse
    return self.parse_token_stream(lexer.tokenize(string))
  File "C:\Users\micha\AppData\Roaming\Python\Python38\site-packages\jsonpath_ng\parser.py", line 55, in parse_token_stream
    return new_parser.parse(lexer = IteratorToTokenStream(token_iterator))
  File "C:\Users\micha\AppData\Roaming\Python\Python38\site-packages\ply\yacc.py", line 333, in parse
    return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc)
  File "C:\Users\micha\AppData\Roaming\Python\Python38\site-packages\ply\yacc.py", line 1201, in parseopt_notrack
    tok = call_errorfunc(self.errorfunc, errtoken, self)
  File "C:\Users\micha\AppData\Roaming\Python\Python38\site-packages\ply\yacc.py", line 192, in call_errorfunc
    r = errorfunc(token)
  File "C:\Users\micha\AppData\Roaming\Python\Python38\site-packages\jsonpath_ng\parser.py", line 69, in p_error
    raise Exception('Parse error at %s:%s near token %s (%s)' % (t.lineno, t.col, t.value, t.type))
Exception: Parse error at 1:6 near token / (SORT_DIRECTION)

有时我可以通过除以倒数来解决这个问题,所以我会使用$.foo * 0.5 来得到结果[1.0]。但是,如果等式的两边都是不同类型(int 或 float)的数值,则这不起作用。所以2 * 0.50.5 * 2 会导致解析错误,但2.0 * 0.5 不会。

如何让部门发挥作用?为什么我不能将浮点数乘以整数?

【问题讨论】:

  • 我在项目中没有找到包括/在内的任何测试。这可能是一个错误。

标签: python parsing jsonpath arithmetic-expressions jsonpath-ng


【解决方案1】:

这些都是语法错误。

  1. 扩展的 JSON 路径允许以包含“排序”列表的括号表达式作为后缀;每个排序都以/\ 开头。为了实现这一点,扩展词法分析器将这两个符号识别为标记SORT_DIRECTION,这优先于将/ 识别为算术运算符。因此,解析器不允许使用/ 作为算术运算符。 (其实问题远不止于此,但这才是本质。)

  2. 由于某种原因,语法作者选择在算术表达式中将NUMBER(实际上是整数)和FLOAT分开,这意味着他们必须枚举可能的组合。他们选择的是:

    jsonpath : NUMBER operator NUMBER
             | FLOAT operator FLOAT
             | ID operator ID
             | NUMBER operator jsonpath
             | FLOAT operator jsonpath
             | jsonpath operator NUMBER
             | jsonpath operator FLOAT
             | jsonpath operator jsonpath
    

    这个语法还有其他问题,但这里的本质是它允许NUMBER operator NUMBERFLOAT operator FLOAT,但不允许NUMBER operator FLOATFLOAT operator NUMBER,这是你观察到的。但是,路径表达式可以与 NUMBERFLOAT 一起使用。

【讨论】:

  • 好吧,作为一个肮脏的修复,我可以分叉库并将除法运算符替换为未使用的符号? (对于 2.,我可以添加 NUMBER operator FLOAT,反之亦然)
  • @EzPizza:当然,然后你可以尝试解决其余的语法错误:-)(例如,运算符优先级根本不起作用;构建语法的方式抑制了冲突警告,其中有 50 个。)
  • @EzPizza:我做了一个小的尝试来修复语法错误,但我不得不停下来,因为我真的不知道目标是什么,而且有很多潜在的歧义。你手边有想要的语法吗?
  • 太棒了!我真正需要的是像$.x / $.y 这样的东西才能工作。除非支持括号,否则我认为添加运算符优先级没有意义,对吧?
  • @ericDuminil:我不知道 jsongraph-ng 包实现的扩展语法的规范。但它是用 Ply 编写的,它采用语法并生成解析器。并且语法有明显的错误,会产生这个问题中报告的意外结果。在我看来,这些都是错误,它们存在于语法中,所以我称它们为语法错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 1970-01-01
  • 2013-08-14
  • 1970-01-01
  • 1970-01-01
  • 2021-06-26
相关资源
最近更新 更多