首页 > 编程语言 >JsonPath使用(Java)

JsonPath使用(Java)

时间:2023-10-18 14:35:08浏览次数:57  
标签:Java users age 30 JsonPath 使用 println name

JsonPath使用(Java)

Java有一些类似于jq的语法库和工具。其中一个叫做JsonPath,它允许使用类似于jq的语法来查询和操作JSON数据。可以使用JsonPath来提取特定的JSON字段、过滤数据、执行计算等操作。另外,还有一些其他的Java库和框架也提供了类似的功能,比如FastJson,Gson和Jackson。这些库可以在Java中更方便地处理和操作JSON数据。

这里只写常用的两种JsonPath和FastJson的使用示例(相对而言,fastjson功能更为强大,语法更丰富)。

JsonPath

用于读取 JSON 文档的 Java DSL。

语法

更多:https://raw.githubusercontent.com/json-path/JsonPath/8a0d2fd594b4a1baab71132cf5ef74889b9976e5/README.md

JSONPATH 描述
$ 根对象,例如 $.name.
@ 处理当前节点的表达式.例如 $.users[?(@.age > 26)]
* 通配符,对象的所有属性,例如$.leader.*
.. deepScan 属性访问,例如 $..name
.<name> 调用当前节点的子项,例如 $.name
['<name>' (, '<name>')] 多个属性访问。例如$['id','name']
[<number> (, <number>)] 数组多个元素访问,其中num是数字,可以是负数,返回数组中的多个元素。例如$[0,3,-2,5]
[start:end] 数组范围访问,其中 start 和 end 是开始小表和结束下标,可以是负数,返回数组中的多个元素。例如 $[0:5]
[?(<expression>)] 过滤表达式,必须为Boolean类型

代码示例

public class TestCase {
    @Test
    public void json() {
        String json = "{\"name\": \"John\", \"age\": 30}";

        ReadContext ctx = JsonPath.parse(json);
        String name = ctx.read("$.name");
        int age = ctx.read( "$.age");

        System.out.println("name: " + name + " ; age: " + age);

        json = "[\"jack\",\"tom\"]";
        ctx = JsonPath.parse(json);
        System.out.println(ctx.jsonString()+ " - "+ ctx.read("$.[0]"));
    }

    @Test
    public void array() {
        String json = "{\"users\": [{\"name\": \"John\", \"age\": 30}, {\"name\": \"Jane\", \"age\": 25}]}";
        ReadContext ctx = JsonPath.parse(json);
        // 使用JsonPath表达式查询数组数据:
        // 使用JsonPath表达式$.users[*].name和$.users[*].age分别从JSON数组中提取了所有用户的姓名和年龄。
        // 使用了通配符[*]来表示所有数组元素
        List<String> names = ctx.read( "$.users[*].name");
        System.out.println(names); // ["John","Jane"]

        String name = ctx.read( "$.users[0].name");
        System.out.println(name); // John

        // 使用JsonPath表达式$.users[0] 来查询数组第一个元素
        Map<String, Object> user = ctx.read( "$.users[0]");
        System.out.println(user); // {name=John, age=30}

        // 迭代数组:
        // 可以使用JsonPath表达式迭代JSON数组并执行其他操作。
        // 例如,以下示例使用JsonPath表达式迭代JSON数组并计算所有用户的平均年龄:
        List<Integer> ages = ctx.read( "$.users[*].age");
        double averageAge = ages.stream().mapToInt(Integer::intValue).average().orElse(0.0);
        System.out.println(averageAge); // 27.5
    }

    @Test
    public void arrayAndCompare() {
        String json = "{\n" +
                "  \"users\": [\n" +
                "    {\n" +
                "      \"name\": \"John\",\n" +
                "      \"age\": 30\n" +
                "    },\n" +
                "    {\n" +
                "      \"name\": \"Jane\",\n" +
                "      \"age\": 25\n" +
                "    },\n" +
                "    {\n" +
                "      \"name\": \"Bob\",\n" +
                "      \"age\": 40\n" +
                "    }\n" +
                "  ]\n" +
                "}";
        ReadContext ctx = JsonPath.parse(json);

        // 获取所有年龄大于30岁的用户的姓名。使用JsonPath表达式的条件语句来实现
        // JsonPath表达式$.users[?(@.age > 30)].name来获取所有年龄大于30岁的用户的姓名。
        // 请注意,条件语句[?(@.age > 30)]来判断每个用户的年龄是否大于30岁,并只获取符合条件的用户的姓名。
        // 可以使用其他条件语句来实现更复杂的逻辑,例如逻辑运算符(如AND和OR)和比较运算符(如等于和不等于)。
        List<String> names = ctx.read( "$.users[?(@.age > 30)].name");
        System.out.println(names); // ["Bob"]

        // JsonPath表达式不支持使用表达式后提取数组下标,如:$.users[?(@.age > 30)][0]
        // https://github.com/json-path/JsonPath/issues/272, 可以使用 fastjson 实现,fastjson支持该语法
        names = ctx.read( "$.users[?(@.age >= 30)][0]"); // 这个表达式现在不支持
        System.out.println(names); // []

        // 获取所有年龄大于30岁的用户
        List<String> users = ctx.read( "$.users[?(@.age > 30)]");
        System.out.println(users); // [{"name":"Bob","age":40}]

        // 获取第一个用户
        Map<String, Object> user = ctx.read( "$.users[0]");
        System.out.println(user); // {name=John, age=30}

        // 获取所有年龄大于30岁的用户中的第一个姓名。由于JsonPath不支持表达式后直接使用数组下标,只能使用Java代码处理
        // 使用JsonPath表达式$.users[?(@.age > 30)].name来获取所有年龄大于30岁的用户的姓名,并使用Java代码来处理结果
        names = ctx.read("$.users[?(@.age > 30)].name");
        String firstName = names.isEmpty() ? null : names.get(0);
        System.out.println(firstName); // Bob

        // 获取所有年龄大于50岁的用户的姓名,并在数组为空时返回默认值"jack",否则返回姓名数组中的第一个值
        names = ctx.read( "$.users[?(@.age > 50)].name");
        firstName = names.isEmpty() ? "jack" : names.get(0);
        System.out.println(names); // []
        System.out.println(firstName); // jack
    }
}

FastJson

fastjson 1.2.0之后的版本支持JSONPath。可以在java框架中当作对象查询语言(OQL)来使用。

语法

JSONPATH描述
$根对象,例如 $.name
[num]数组访问,其中 num 是数字,可以是负数。例如 $[0].leader.departments[-1].name
[num0,num1,num2...]数组多个元素访问,其中 num 是数字,可以是负数,返回数组中的多个元素。例如 $[0,3,-2,5]
[start:end]数组范围访问,其中 start 和 end 是开始小表和结束下标,可以是负数,返回数组中的多个元素。例如 $[0:5]
[start:end :step]数组范围访问,其中 start 和 end 是开始小表和结束下标,可以是负数;step 是步长,返回数组中的多个元素。例如 $[0:5:2]
[?(key)]对象属性非空过滤,例如 $.departs[?(name)]
[key> 123]数值类型对象属性比较过滤,例如 $.departs[id>= 123],比较操作符支持 =,!=,>,>=,<,<=
[key = '123']字符串类型对象属性比较过滤,例如 $.departs[name = '123'],比较操作符支持 =,!=,>,>=,<,<=
[key like 'aa%']字符串类型 like 过滤,
例如 $.departs[name like 'sz*'],通配符只支持 %
支持 not like
[key rlike 'regexpr']字符串类型正则匹配过滤,
例如 departs[name rlike 'aa(.)*'],
正则语法为 jdk 的正则语法,支持 not rlike
[key in ('v0', 'v1')]IN 过滤, 支持字符串和数值类型
例如:
$.departs[name in ('wenshao','Yako')]
$.departs[id not in (101,102)]
[key between 234 and 456]BETWEEN 过滤, 支持数值类型,支持 not between
例如:
$.departs[id between 101 and 201]
$.departs[id not between 101 and 201]
length() 或者 size()数组长度。例如 $.values.size()
支持类型 java.util.Map 和 java.util.Collection 和数组
keySet()获取 Map 的 keySet 或者对象的非空属性名称。例如 $.val.keySet()
支持类型:Map 和普通对象
不支持:Collection 和数组(返回 null)
.属性访问,例如 $.name
..deepScan 属性访问,例如 $..name
*对象的所有属性,例如 $.leader.*
['key']属性访问。例如 $['name']
['key0','key1']多个属性访问。例如 $['id','name']

语法示例

JSONPath语义
$根对象
$[-1]最后元素
$[:-2]第 1 个至倒数第 2 个
$[1:]第 2 个之后所有元素
$[1,2,3]集合中 1,2,3 个元素

代码示例

public class TestCase {

    private String json = "{\"users\": [{\"name\": \"John\", \"age\": 30}, {\"name\": \"Jane\", \"age\": 25}]}";

    @Test
    public void json() {
        JSONObject jsonObject = JSON.parseObject(json);
        JSONArray users = (JSONArray) JSONPath.eval(jsonObject, "$.users");
        System.out.println(users); // [{"name":"John","age":30},{"name":"Jane","age":25}]

        JSONArray names = (JSONArray) JSONPath.eval(jsonObject, "$.users.name");
        System.out.println(names); // ["John","Jane"]

        String name = (String) JSONPath.eval(jsonObject, "$.users[1].name");
        System.out.println(name); // Jane
    }

    /**
     * use && and || to combine multiple predicates
     * [?(@.price < 10 && @.category == 'fiction')] , [?(@.category == 'reference' || @.price > 10)].
     *
     * use ! to negate a predicate
     * [?(!(@.price < 10 && @.category == 'fiction'))].
     */
    @Test
    public void array() {
        JSONObject jsonObject = JSON.parseObject(json);

        JSONArray users = (JSONArray) JSONPath.eval(jsonObject, "$.users[?(@.age > 26)]");
        System.out.println("年龄大于26的 user:" + users); // [{"name":"John","age":30}]

        users = (JSONArray) JSONPath.eval(jsonObject, "$.users[?(@.age > 20 && @.age < 30)]");
        System.out.println("年龄大于20并且小于30的 user:" + users); // [{"name":"Jane","age":25}]

        users = (JSONArray) JSONPath.eval(jsonObject, "$.users[?(@.age > 20 && @.name like 'Jo%')]");
        System.out.println("年龄大于20并且name以'Jo'开头的 user:" + users); // [{"name":"John","age":30}]

        JSONObject user = (JSONObject) JSONPath.eval(jsonObject, "$.users[?(@.age > 20)][0]");
        System.out.println("年龄大于20的第一个 user:" + user); // {"name":"John","age":30}

        JSONArray names = (JSONArray) JSONPath.eval(jsonObject, "$.users[?(@.age > 26)].name");
        System.out.println("年龄大于26的 name:" + names); // ["John"]

        names = (JSONArray) JSONPath.eval(jsonObject, "$.users[?(@.age >= 20)].name");
        System.out.println("年龄大于20的 name:" + names); // ["John","Jane"]

        String name = (String) JSONPath.eval(jsonObject, "$.users[?(@.age >= 20)][1].name");
        System.out.println("年龄大于20的第一个name:" + name); // Jane
    }
}

标签:Java,users,age,30,JsonPath,使用,println,name
From: https://www.cnblogs.com/tomoncle/p/17772263.html

相关文章

  • 快速查看硬盘使用的分区类型:MBR或GPT
    快速查看硬盘使用的分区类型:MBR或GPT对硬盘进行分区可能没有你想象的那么简单,重要的是要知道采用哪种样式。当前只有两种样式:主引导记录(MBR)和GUID分区表(GPT)。如果你不了解这些术语,可以在我以前的文章中了解这些术语以及哪种分区样式更好。我们今天讨论的主题是如何在Window......
  • linux centos7kettle使用Carte
    1.下载安装kettle的方法请自行百度2.启动carte服务进入kettle目录cd/opt/data-integration方式一#windowsCarte.batipport#例:Carte.bat 192.168.x.x 8080#linux./carte.shipport#例:./carte.sh 192.168.x.x 8080方式二编辑data-integration/pwd/carte-confi......
  • Java拾贝第五天——抽象和接口
    Java拾贝不建议作为0基础学习,都是本人想到什么写什么如果父类的方法本身不需要实现,仅仅是为了定义方法。目的是让子类去重写它,那么,可以把父类的方法声明为抽象(abstract)方法classCandy{publicabstractvoidsell();}//无法通过编译若某类中拥有一个或若干个抽象方......
  • 实验二 Linux命令使用(二)
    实验内容及步骤:(1)进入家目录,创建自己的子目录,进入该子目录,运行date>file1,然后运行catfile1,看到什么信息?“>”是什么符号?答:输出重定向操作符解释“date>file1”的含义:答:将当前日期和时间写入名为file1的文件中。(2)运行mandate>>file1,再运行catfile1,看到什么?mandat......
  • java在ubuntu上部署生产环境(适合小项目)
    一、概述需求:将SpringBoot项目打包成jar包,快速部署到云服务器的生产环境。(小型项目)二、部署步骤1.配置好项目运行所需的环境2.将jar包上传到服务器的指定目录(可以自定义)。如:/usr/local/或/tony/jar/(这是个自定义目录)3.创建一个服务文件并将其放入:/etc/system......
  • java
    "循环加载"(circulardependency)指的是,a脚本的执行依赖b脚本,而b脚本的执行又依赖a脚本。 css复制代码//a.jsvarb=require('b');//b.jsvara=require('a');通常,"循环加载"表示存在强耦合,如果处理不好,还可能导致递归加载,使得程序无法执行,因此应该避免出现......
  • 使用vs自带的dumpbin工具 查询依赖库
    dumpbin工具 使用vs自带的dumpbin工具:  打开VS命令行2.执行“dumpbin/dependents+dll/exe路径” ......
  • 【有趣的小细节】在Java中native方法hashcode()默认是如何生成哈希码的?
    之前看其他文章说,hashcode是根据对象的内存地址生成的。但为了满足自己的好奇心,同时验证这个结论是否是真实的,我半个月前深究了一下。今天突然想起来这回事了,把结论记录一下。结论目前hashcode的方式有以下六种算法:HashCodeMode==0:由操作系统生成的一个随机数。HashCodeMode==1:基......
  • C语言-结构体使用
    C语言-结构体使用#include<stdio.h>#include<stdlib.h>#include<string.h>//结构体/*结构体定义*/structPerson{ charname[20]; intage;};intmain(){/*结构体赋值*/ structPersonperson1={"Tom",20 }; printf("Name:%s,age:......
  • 使用ffmpeg将opencv捕获的摄像头数据推流到本地rtsp器上
    首先,为什么使用opencv?答:方便对视频进行处理,各种深度学习网络就有了用物之地。具体流程参考的FFmpeg/opencv+C++实现直播拉流和直播推流(对视频帧进行处理)_c++ffmpeg拉流_酒神无忧的博客-CSDN博客,但是细节不同。简述一下流程:使用opencv从摄像头中读取数据。将cv::Mat转换为A......