jayway json-path 2.9.0版本中使用!=过滤排除字段失效的问题咨询
我明白你遇到的问题——Jayway JsonPath的实现和Goessner原版的在线工具确实存在一些行为差异,你写的表达式在Goessner工具里能工作,但在Jayway 2.9.0里不行,核心原因是两者对@和过滤逻辑的解析方式不一样。
先给你拆解一下问题:你原来写的$.address[?(@!=$.address.city)]在Jayway里逻辑是错的——当你在$.address这个对象上使用[?()]过滤时,这里的@指代的是整个address对象,而不是单个属性值。你拿整个对象和$.address.city的字符串值比较,显然逻辑不成立,所以得不到预期结果。
下面给你两种可靠的解决方案,都能得到你想要的[naist street, 630-0192]输出:
方法1:显式指定要提取的字段(推荐)
如果要排除的字段很少(比如这里只排除city),直接显式列出需要的字段是最简单、最不容易出错的方式:
Object filtered = JsonPath.read(json, "$.address.streetAddress, $.address.postalCode");
这个表达式直接定位到streetAddress和postalCode两个字段,Jayway会自动把它们打包成数组返回,完全符合你的预期。
方法2:动态排除指定字段(适合不确定其他字段的场景)
如果你的场景是需要动态排除某个字段(比如不知道address下还有哪些其他字段,只确定要排除city),可以用Jayway支持的$key变量来过滤属性键:
Object filtered = JsonPath.read(json, "$..address.*[?($key != 'city')]");
这里的$..address.*会遍历address下的所有属性值,$key指代当前属性的键名,通过$key != 'city'过滤掉city对应的属性,剩下的就是你要的结果。
修改后的完整可运行代码
package org.example; import com.jayway.jsonpath.JsonPath; public class JavaJsonPath { public static void main(String[] args) { String json = """ { "firstName": "John", "lastName" : "doe", "age" : 26, "address" : { "streetAddress": "naist street", "city" : "Nara", "postalCode" : "630-0192" }, "phoneNumbers": [ { "type" : "iPhone", "number": "0123-4567-8888" }, { "type" : "home", "number": "0123-4567-8910" } ] } """; // 显式指定字段的方式 Object result1 = JsonPath.read(json, "$.address.streetAddress, $.address.postalCode"); System.out.println("Without 'city' (显式指定): " + result1); // 动态排除city的方式 Object result2 = JsonPath.read(json, "$..address.*[?($key != 'city')]"); System.out.println("Without 'city' (动态排除): " + result2); } }
运行这段代码,两种方式都会输出你想要的[naist street, 630-0192]。
简单总结一下:Jayway JsonPath和Goessner原版的语法兼容性不是100%,遇到这种对象属性过滤的场景,优先用显式指定字段的方式(更可靠);如果需要动态排除,一定要用Jayway支持的$key变量来处理属性键的过滤。
内容来源于stack exchange

