• JsonPath 基本使用


    一、JSONPath 介绍

    XML 格式的优点之一是可以使用很多工具来分析、转换和有选择地从 XML 文档中提取数据。 XPath 就是这些强大的工具之一。而对于 JSON 文档,也有类似的 JSONPath 规范(可以说是事实上的业内标准)。

    通俗易懂地讲,就是可以通过形如 $.tool.jsonpath.creator 的「路径」来表示 JSON 文档内部嵌套的任意属性与值。

    Jayway JsonPath 就是 JSONPath 规范的一个广为使用的 Java 实现。本文就简要介绍该库的基本使用。

    此外,alibaba 的 fastjson 也支持 JSONPath。

    二、使用示例

    以如下的 JSON 文本举例:

    {
        "tool": {
            "jsonpath": {
                "creator": {
                    "name": "Jayway Inc.",
                    "location": [
                        "Malmo",
                        "San Francisco",
                        "Helsingborg"
                    ]
                }
            }
        },
        "book": [
            {
                "title": "Beginning JSON",
                "price": 49.99
            },
            {
                "title": "JSON at Work",
                "price": 29.99
            }
        ]
    }
    

    2.1 基本语法:

    • $ 表示根节点,@ 表示当前节点,* 表示通配符;
    • 使用 . 或者 [] 分隔节点及其相邻节点。例如,用 $.tool.jsonpath.creator.location[2] 或者 $['tool']['jsonpath']['creator']['location'][2] 都可以获取到上面 JSON 文本里的"Helsingborg"

    2.2 主要 API:

    • <T> T JsonPath.read(String jsonString, String jsonPath, Predicate... filters);
    • <T> T JsonPath.parse(String jsonString).read(String jsonPath, Predicate... filters);

    话不多说,直接上代码:

    import com.jayway.jsonpath.Configuration;
    import com.jayway.jsonpath.DocumentContext;
    import com.jayway.jsonpath.JsonPath;
    import com.jayway.jsonpath.spi.json.GsonJsonProvider;
    import com.jayway.jsonpath.spi.json.JacksonJsonNodeJsonProvider;
    import com.jayway.jsonpath.spi.mapper.GsonMappingProvider;
    import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
    
    public class JsonPathTest {
    
        /**
         * <pre> json:
         * {
         *     "tool": {
         *         "jsonpath": {
         *             "creator": {
         *                 "name": "Jayway Inc.",
         *                 "location": [
         *                     "Malmo",
         *                     "San Francisco",
         *                     "Helsingborg"
         *                 ]
         *             }
         *         }
         *     },
         *     "book": [
         *         {
         *             "title": "Beginning JSON",
         *             "price": 49.99
         *         },
         *         {
         *             "title": "JSON at Work",
         *             "price": 29.99
         *         }
         *     ]
         * }
         * </pre>
         */
        private static final String json = "{\"tool\":{\"jsonpath\":{\"creator\":{\"name\":\"Jayway Inc.\",\"location\":[\"Malmo\",\"San Francisco\",\"Helsingborg\"]}}},\"book\":[{\"title\":\"Beginning JSON\",\"price\":49.99},{\"title\":\"JSON at Work\",\"price\":29.99}]}";
    
        public static void main(String[] args) throws Exception {
            String path1 = "$.tool.jsonpath.creator.location[1]";
            String path2 = "$['tool']['jsonpath']['creator']['location'][*]";
            String path3 = "$.book..title";
            String path4 = "$.book[1]";
    
            DocumentContext jsonContext = JsonPath.parse(json);
            // 读出来的对象是 1.Java原生类型 或者 2.JsonPath 库的类型
            Object o1 = JsonPath.read(json, path1);   // class java.lang.String
            Object o2 = jsonContext.read(path2);   // class net.minidev.json.JSONArray
            // 可以直接用正确的类型接收返回值
            net.minidev.json.JSONArray o3 = jsonContext.read(path3);
            java.util.LinkedHashMap o4 = jsonContext.read(path4);   // 很奇怪 o4 的类型是 Map 而不是 net.minidev.json.JSONObject
    
    
            // 如果想使用 Gson 的 JSON 动态类型,需要
            Configuration gsonConf = Configuration.builder()
                    .jsonProvider(new GsonJsonProvider())
                    .mappingProvider(new GsonMappingProvider())
                    .build();
            DocumentContext gsonContext = JsonPath.using(gsonConf).parse(json);
            Object g1 = gsonContext.read(path1);   // class com.google.gson.JsonPrimitive
            Object g2 = gsonContext.read(path2);   // class com.google.gson.JsonObject
            com.google.gson.JsonArray g3 = gsonContext.read(path3);
            com.google.gson.JsonObject g4 = gsonContext.read(path4);
    
    
            // 如果想使用 Jackson 的 JSON 动态类型,需要
            Configuration jacksonConf = Configuration.builder()
                    .jsonProvider(new JacksonJsonNodeJsonProvider()) // 注意:不是 JacksonJsonProvider
                    .mappingProvider(new JacksonMappingProvider())
                    .build();
            DocumentContext jacksonContext = JsonPath.using(jacksonConf).parse(json);
            Object k1 = jacksonContext.read(path1);   // class com.fasterxml.jackson.databind.node.TextNode
            Object k2 = jacksonContext.read(path2);   // class com.fasterxml.jackson.databind.node.ObjectNode
            com.fasterxml.jackson.databind.node.ArrayNode k3 = jacksonContext.read(path3);
            com.fasterxml.jackson.databind.node.ArrayNode k4 = jacksonContext.read(path4);
        }
    }
    

    注意几个地方:

    • read()方法返回值使用了泛型,所以可以用任意类型来接收返回值。但是如果使用了错误的类型,则会抛出java.lang.ClassCastException
    • 如果想使用Gson或者Jackson的 JSON 动态类型,需要配置Configuration后再解析。至于这两个 JSON 库的基本介绍与使用在我的前一篇博文中有讲。

    最后,更多语法以及高级用法(如PredicatesOptions等)可以自行去查阅 JSONPath 规范Jayway JsonPath 的文档。

    参考:
    https://www.baeldung.com/guide-to-jayway-jsonpath

  • 相关阅读:
    angular9的学习(十)
    本周学习总结
    本周学习总结
    angular9的学习(九)
    本周学习总结
    Web地图呈现原理
    小程序Canvas性能优化实战
    地图SDK全新版本v4.3.0上线
    硬核干货来了!手把手教你实现热力图!
    地图SDK全面升级 – 数十项新功能及优化等你来体验
  • 原文地址:https://www.cnblogs.com/recycer/p/16274298.html
Copyright © 2020-2023  润新知