ToB企服应用市场:ToB评测及商务社交产业平台

标题: JsonPath详解 [打印本页]

作者: 数据人与超自然意识    时间: 2024-8-10 19:52
标题: JsonPath详解
JsonPath

1、概述

JsonPath是用来解析多层嵌套的JSON数据。可以以为JsonPath就是JSON版本的XPath。它是一种信息抽取类库,是从JSON文档中抽取指定信息的工具。JsonPath对于JSON来说,就相当于XPath之于XML。
JsonPath在线解析:https://jsonpath.com/
2、JsonPath语法

2.1、操纵符

语法寄义$表示根节点@当前节点.<节点名称>获取子节点[<节点名称1>(,<节点名称2>)]获取子节点,与点号差别,这里可以获取多个子节点*匹配所有元素节点..获取子孙节点,无论嵌套多少层,都可以获取到[<下标1>(,<下标2>)]表示一个或多个下标[start:end:step]表示切片语法[?(<表达式>)]过滤器表达式,表达式效果必须是布尔值()支持表达式盘算 2.2、函数

可以在JsonPath表达式执行后进行调用,其输入表达式的效果。
函数描述输出min()提供数字数组的最小值Doublemax()提供数字数组的最大值Doubleavg()提供数字数据的均匀值Doublestddev()提供数字数组的标准偏差值Doublelength()提供数组的长度Integersum()提供数字数组的和值Doublekeys()提供属性键(终端自键~的替代选择)Set<E>concat(X)提供路径输出的合并版本,并添加一个新项目like inputappend(X)为 json 路径输出数组添加项目like inputfirst()提供数组的第一个项目Depends on the arraylast()提供数组的末了一项Depends on the arrayindex(X)提供索引数组的项: X,如果 X 为负数,则向后取值Depends on the array 2.3、过滤器

过滤器是用于过滤数组的逻辑表达式,一个通常的表达式形如:[?(@.age > 18)],可以通过逻辑表达式&&或||组合多个过滤器表达式,例如[?(@.price < 10 && @.category == ‘fiction’)],字符串必须用单引号困绕,例如[?(@.color == ‘blue’)]。
操纵符描述==即是符号,但数字1不即是字符1(1 is not equal to ‘1’)!=不即是<小于<=小于即是>大于即是>=大于即是=~判定是否符合正则表达式,例如[?(@.name =~ /foo.*?/i)]in属于,例如[?(@.size in ['S', 'M'])]nin排除符号size左侧(数组或字符串)的大小应与右侧一致empty数组或字符串)应为空subsetof左是右的子集 [?(@.sizes subsetof [‘S’, ‘M’, ‘L’])]anyof左与右有交集 [?(@.sizes anyof [‘M’, ‘L’])]noneof左边与右边没有交集 [?(@.sizes noneof [‘M’, ‘L’])] 2.4、示例

  1. {
  2.     "store": {
  3.         "book": [
  4.             {
  5.                 "category": "reference",
  6.                 "author": "Nigel Rees",
  7.                 "title": "Sayings of the Century",
  8.                 "price": 8.95
  9.             },
  10.             {
  11.                 "category": "fiction",
  12.                 "author": "Evelyn Waugh",
  13.                 "title": "Sword of Honour",
  14.                 "price": 12.99
  15.             },
  16.             {
  17.                 "category": "fiction",
  18.                 "author": "Herman Melville",
  19.                 "title": "Moby Dick",
  20.                 "isbn": "0-553-21311-3",
  21.                 "price": 8.99
  22.             },
  23.             {
  24.                 "category": "fiction",
  25.                 "author": "J. R. R. Tolkien",
  26.                 "title": "The Lord of the Rings",
  27.                 "isbn": "0-395-19395-8",
  28.                 "price": 22.99
  29.             }
  30.         ],
  31.         "bicycle": {
  32.             "color": "red",
  33.             "price": 19.95
  34.         }
  35.     },
  36.     "expensive": 10
  37. }
复制代码
JsonPathResult$.store.book
  • .author所有册本的作者$..author所有作者$..book[2]第3本数$..book[0,1]前2本数$..book[1:3]切片操纵,从索引 1(含)到索引 3(不含)的所有册本$..book[-1:]倒数第一本数$..book[?(@.isbn)]所有有 ISBN 编号的册本$.store.book[?(@.price < 10)]代价低于10的所有数据$..book.length册本的数目 3、基于Java的使用

    Jayway JsonPath则提供了Java版本的实现,方便开发者进行集成使用。
    Maven依赖:
    1. <!--Json Path-->
    2. <dependency>
    3.   <groupId>com.jayway.jsonpath</groupId>
    4.   <artifactId>json-path</artifactId>
    5.   <version>2.7.0</version>
    6. </dependency>
    复制代码
    3.1、使用方式

    使用 JsonPath 最简朴直接的方法是通过静态读取 API。
    1. public class Demo {
    2.     private String jsonStr = "{\n" +
    3.             "  "store": {\n" +
    4.             "    "book": [\n" +
    5.             "      {\n" +
    6.             "        "category": "reference",\n" +
    7.             "        "author": "Nigel Rees",\n" +
    8.             "        "title": "Sayings of the Century",\n" +
    9.             "        "price": 8.95\n" +
    10.             "      },\n" +
    11.             "      {\n" +
    12.             "        "category": "fiction",\n" +
    13.             "        "author": "Evelyn Waugh",\n" +
    14.             "        "title": "Sword of Honour",\n" +
    15.             "        "price": 12.99\n" +
    16.             "      },\n" +
    17.             "      {\n" +
    18.             "        "category": "fiction",\n" +
    19.             "        "author": "Herman Melville",\n" +
    20.             "        "title": "Moby Dick",\n" +
    21.             "        "isbn": "0-553-21311-3",\n" +
    22.             "        "price": 8.99\n" +
    23.             "      },\n" +
    24.             "      {\n" +
    25.             "        "category": "fiction",\n" +
    26.             "        "author": "J. R. R. Tolkien",\n" +
    27.             "        "title": "The Lord of the Rings",\n" +
    28.             "        "isbn": "0-395-19395-8",\n" +
    29.             "        "price": 22.99\n" +
    30.             "      }\n" +
    31.             "    ],\n" +
    32.             "    "bicycle": {\n" +
    33.             "      "color": "red",\n" +
    34.             "      "price": 19.95\n" +
    35.             "    }\n" +
    36.             "  },\n" +
    37.             "  "expensive": 10\n" +
    38.             "}";
    39.     @Test
    40.     public void test1() {
    41.         List<String> authors = JsonPath.read(jsonStr, "$.store.book[*].author");
    42.         //["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]
    43.         System.out.println(authors);
    44.     }
    45. }
    复制代码
    如果你只读取一次,这没有问题。如果还必要读取其他路径,这就不是办法了,由于每次调用 JsonPath.read(…) 都会对文档进行解析。为了避免这个问题,可以先解析 json。
    1. @Test
    2. public void test2() {
    3.     final Object document = Configuration.defaultConfiguration().jsonProvider().parse(jsonStr);
    4.     String author0 = JsonPath.read(document, "$.store.book[0].author");
    5.     String author1 = JsonPath.read(document, "$.store.book[1].author");
    6.     //Nigel Rees
    7.     System.out.println(author0);
    8.     //Evelyn Waugh
    9.     System.out.println(author1);
    10. }
    复制代码
    JsonPath还提供了流通的应用程序接口。这也是最灵活的一种:
    1. @Test
    2. public void test3() {
    3.     DocumentContext ctx = JsonPath.parse(jsonStr);
    4.     List<String> authorsOfBooksWithISBN = ctx.read("$.store.book[?(@.isbn)].author");
    5.     //["Herman Melville","J. R. R. Tolkien"]
    6.     System.out.println(authorsOfBooksWithISBN);
    7.     //[{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},
    8.     // {"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}]
    9.     List<Map<String, Object>> expensiveBooks = JsonPath.using(Configuration.defaultConfiguration())
    10.             .parse(jsonStr)
    11.             .read("$.store.book[?(@.price > 10)]", List.class);
    12.     System.out.println(expensiveBooks);
    13. }
    复制代码
    3.2、返回类型

    在 Java 中使用 JsonPath 时,了解效果的预期类型非常告急。JsonPath 会自动尝试将效果转换为调用者期望的类型。
    1. //Nigel Rees
    2. String author = JsonPath.parse(jsonStr).read("$.store.book[0].author");
    3. //java.lang.ClassCastException: java.lang.String cannot be cast to java.util.List
    4. List<String> list = JsonPath.parse(jsonStr).read("$.store.book[0].author");
    复制代码
    在评估一条路径时,你必要了解一条路径何时是确定的这一概念。如果一条路径包含以下内容,那么它就是不确定的:

    无穷路径总是返回一个列表(由当前 JsonProvider 表示)。
    默认情况下,MappingProvider SPI 会提供一个简朴对象映射器。这答应你指定想要的返回类型,而 MappingProvider 会尝试执行映射。下面的示例演示了 Long 和 Date 之间的映射。
    1. String json = "{"date_as_long":  1411455611975}";
    2. Date date = JsonPath.parse(json).read("$['date_as_long']", Date.class);
    3. //Tue Sep 23 15:00:11 CST 2014
    4. System.out.println(date);
    复制代码
    如果将 JsonPath 配置为使用 JacksonMappingProvider、GsonMappingProvider 或 JakartaJsonProvider,乃至可以将 JsonPath 输出直接映射到 POJO 中。
    1. Book book = JsonPath.parse(jsonStr).read("$.store.book[0]", Book.class);
    2. //Book{category='reference', title='Sayings of the Century', author='Nigel Rees', price=8.95, isbn='null'}
    3. System.out.println(book);
    复制代码
    要获取完整的类属类型信息,请使用 TypeRef。
    1. //注意,默认的Json-smart provider不支持TypeRef,可以使用Jackson或Gson Provider
    2. TypeRef<List<String>> typeRef = new TypeRef<List<String>>() {};
    3. List<String> titles = JsonPath.parse(jsonStr).read("$.store.book[*].title", typeRef);
    4. System.out.println(titles);
    复制代码
    3.3、JsonProvider

    在Jayway JsonPath中提供了多种JsonProvider,此中默认的为JsonSmartJsonProvider。这里我们期望可以或许直接对读取的数据进行反序列化,这里我们选用JacksonJsonProvider,此时要求jackson-databind依赖的版本至少为2.4.5。
    1. <!--Jackson-->
    2. <dependency>
    3.     <groupId>com.fasterxml.jackson.core</groupId>
    4.     <artifactId>jackson-databind</artifactId>
    5.     <version>2.11.3</version>
    6. </dependency>
    复制代码
    1. @AllArgsConstructor
    2. @NoArgsConstructor
    3. @Builder
    4. @Data
    5. class Book {
    6.     private String category;
    7.     private String title;
    8.     private String author;
    9.     private Double price;
    10.     private String isbn;
    11. }
    复制代码
    1. public class JsonProviderTest {
    2.     private String jsonStr = "{\n" +
    3.             "  "store": {\n" +
    4.             "    "book": [\n" +
    5.             "      {\n" +
    6.             "        "category": "reference",\n" +
    7.             "        "author": "Nigel Rees",\n" +
    8.             "        "title": "Sayings of the Century",\n" +
    9.             "        "price": 8.95\n" +
    10.             "      },\n" +
    11.             "      {\n" +
    12.             "        "category": "fiction",\n" +
    13.             "        "author": "Evelyn Waugh",\n" +
    14.             "        "title": "Sword of Honour",\n" +
    15.             "        "price": 12.99\n" +
    16.             "      },\n" +
    17.             "      {\n" +
    18.             "        "category": "fiction",\n" +
    19.             "        "author": "Herman Melville",\n" +
    20.             "        "title": "Moby Dick",\n" +
    21.             "        "isbn": "0-553-21311-3",\n" +
    22.             "        "price": 8.99\n" +
    23.             "      },\n" +
    24.             "      {\n" +
    25.             "        "category": "fiction",\n" +
    26.             "        "author": "J. R. R. Tolkien",\n" +
    27.             "        "title": "The Lord of the Rings",\n" +
    28.             "        "isbn": "0-395-19395-8",\n" +
    29.             "        "price": 22.99\n" +
    30.             "      }\n" +
    31.             "    ],\n" +
    32.             "    "bicycle": {\n" +
    33.             "      "color": "red",\n" +
    34.             "      "price": 19.95\n" +
    35.             "    }\n" +
    36.             "  },\n" +
    37.             "  "expensive": 10\n" +
    38.             "}";
    39.     @Test
    40.     public void test() {
    41.         //使用JacksonJsonProvider
    42.         Configuration configuration = Configuration
    43.                 .builder()
    44.                 .mappingProvider(new JacksonMappingProvider())
    45.                 .build();
    46.         ReadContext ctx = JsonPath.using(configuration).parse(jsonStr);
    47.         TypeRef<List<Book>> typeRef = new TypeRef<List<Book>>() {};
    48.         List<Book> books = ctx.read("$.store.book[*]", typeRef);
    49.         books.forEach(System.out::println);
    50.     }
    51. }
    复制代码
    1. Book{category='reference', title='Sayings of the Century', author='Nigel Rees', price=8.95, isbn='null'}
    2. Book{category='fiction', title='Sword of Honour', author='Evelyn Waugh', price=12.99, isbn='null'}
    3. Book{category='fiction', title='Moby Dick', author='Herman Melville', price=8.99, isbn='0-553-21311-3'}
    4. Book{category='fiction', title='The Lord of the Rings', author='J. R. R. Tolkien', price=22.99, isbn='0-395-19395-8'}
    复制代码
    3.4、谓词

    在JsonPath中创建过滤器谓词有三种差别的方法:

    1、内联谓词

    内联谓词是在路径中界说的谓词。
    可以使用 && 和 || 组合多个谓词 [?(@.price < 10 && @.category == ‘fiction’)] , [?(@.category == ‘reference’ || @.price > 10)]。
    可以使用! 来否定一个谓词 [?(!(@.price < 10 && @.category == ‘fiction’))] 。
    1. @Test
    2. public void test1() {
    3.     List<Map<String, Object>> books = JsonPath.parse(jsonStr)
    4.             .read("$.store.book[?(@.price < 10)]");
    5.     books.forEach(System.out::println);
    6.     //{category=reference, author=Nigel Rees, title=Sayings of the Century, price=8.95}
    7.     //{category=fiction, author=Herman Melville, title=Moby Dick, isbn=0-553-21311-3, price=8.99}
    8.     books = JsonPath.parse(jsonStr)
    9.             .read("$.store.book[?(!@.price < 10)]");
    10.     books.forEach(System.out::println);
    11.     //{category=reference, author=Nigel Rees, title=Sayings of the Century, price=8.95}
    12.     //{category=fiction, author=Herman Melville, title=Moby Dick, isbn=0-553-21311-3, price=8.99}
    13. }
    复制代码
    2)、过滤器谓词

    如下所示,可以使用过滤器 API 构建谓词:
    1. @Test
    2. public void test2() {
    3.     Filter cheapFictionFilter = Filter.filter(
    4.             Criteria.where("price").lte(10)
    5.     );
    6.     //注意路径中过滤器的占位符 ?
    7.     //当提供多个过滤器时,它们将按顺序应用,其中占位符的数量必须与提供的过滤器数量相匹配。
    8.     //可以在一个过滤器操作中指定多个谓词占位符[?, ?],但两个谓词必须匹配。
    9.     List<Map<String, Object>> books = JsonPath.parse(jsonStr)
    10.             .read("$.store.book[?]", cheapFictionFilter);
    11.     books.forEach(System.out::println);
    12.     //{category=reference, author=Nigel Rees, title=Sayings of the Century, price=8.95}
    13.     //{category=fiction, author=Herman Melville, title=Moby Dick, isbn=0-553-21311-3, price=8.99}
    14.     //过滤器还可以与OR和AND组合使用
    15.     Filter f = Filter.filter(Criteria.where("price").lte(10))
    16.             .and(Criteria.where("isbn").exists(true));
    17.     books = JsonPath.parse(jsonStr)
    18.             .read("$.store.book[?]", f);
    19.     books.forEach(System.out::println);
    20.     //{category=fiction, author=Herman Melville, title=Moby Dick, isbn=0-553-21311-3, price=8.99}
    21. }
    复制代码
    3)、自界说谓词

    1. @Test
    2. public void test3() {
    3.     //自定义谓词
    4.     Predicate booksWithISBN = new Predicate() {
    5.         @Override
    6.         public boolean apply(PredicateContext ctx) {
    7.             return ctx.item(Map.class).containsKey("isbn");
    8.         }
    9.     };
    10.     List<Map<String, Object>> books = JsonPath.parse(jsonStr)
    11.             .read("$.store.book[?]", booksWithISBN);
    12.     books.forEach(System.out::println);
    13.     //{category=fiction, author=Herman Melville, title=Moby Dick, isbn=0-553-21311-3, price=8.99}
    14.     //{category=fiction, author=J. R. R. Tolkien, title=The Lord of the Rings, isbn=0-395-19395-8, price=22.99}
    15. }
    复制代码
    4)、示例

    1. {
    2.     "store":{
    3.         "book":[
    4.             {
    5.                 "category":"reference",
    6.                 "author":"Nigel Rees",
    7.                 "title":"Sayings of the Century",
    8.                 "price":8.95
    9.             },
    10.             {
    11.                 "category":"fiction",
    12.                 "author":"Evelyn Waugh",
    13.                 "title":"Sword of Honour",
    14.                 "price":12.99
    15.             },
    16.             {
    17.                 "category":"fiction",
    18.                 "author":"Herman Melville",
    19.                 "title":"Moby Dick",
    20.                 "isbn":"0-553-21311-3",
    21.                 "price":8.99
    22.             },
    23.             {
    24.                 "category":"fiction",
    25.                 "author":"J. R. R. Tolkien",
    26.                 "title":"The Lord of the Rings",
    27.                 "isbn":"0-395-19395-8",
    28.                 "price":22.99
    29.             }
    30.         ],
    31.         "bicycle":{
    32.             "color":"red",
    33.             "price":19.95
    34.         },
    35.         "clothes":[
    36.             {
    37.                 "name":"牛仔裤",
    38.                 "sizes":"S",
    39.                 "price":94
    40.             },
    41.             {
    42.                 "name":"背心",
    43.                 "sizes":"M",
    44.                 "price":48
    45.             },
    46.             {
    47.                 "name":"裙子",
    48.                 "sizes":["S", "M"],
    49.                 "price":1.24
    50.             },
    51.             {
    52.                 "name":"羊毛衫",
    53.                 "sizes":["XS", "XL"],
    54.                 "price":78.99
    55.             },
    56.             {
    57.                 "name":"Polo衫",
    58.                 "sizes":["XS", "XL", "M"],
    59.                 "price":18.99
    60.             }
    61.         ]
    62.     },
    63.     "expensive":10
    64. }
    复制代码
    1. @Test
    2. public void test() {
    3.     //使用JacksonJsonProvider
    4.     Configuration configuration = Configuration
    5.             .builder()
    6.             .mappingProvider(new JacksonMappingProvider())
    7.             .build();
    8.     ReadContext ctx = JsonPath.using(configuration)
    9.             .parse(jsonStr);
    10.     //方式一:内联谓词
    11.     TypeRef<List<Clothes>> typeRef = new TypeRef<List<Clothes>>() {};
    12.     final List<Clothes> clothes1 = ctx.read("$.store.clothes[?(@.price > 50 || @.sizes anyof ['M'])]", typeRef);
    13.     System.out.println("************** clothes1 ***************");
    14.     clothes1.forEach(System.out::println);
    15.     //方式二:Filter谓词
    16.     Filter filter = Filter.filter(Criteria.where("price").gt(50))
    17.             .or(Criteria.where("sizes").anyof(Arrays.asList("M")));
    18.     //使用谓词占位符?
    19.     Clothes[] clothes2 = ctx.read("$.store.clothes[?]", Clothes[].class, filter);
    20.     System.out.println("************** clothes2 ***************");
    21.     for (Clothes clothes : clothes2) {
    22.         System.out.println(clothes);
    23.     }
    24.     //方式三:自定义谓词
    25.     Predicate rule = (context) -> {
    26.         final Map map = context.item(Map.class);
    27.         boolean b1 = false;
    28.         Object priceObj = map.getOrDefault("price", null);
    29.         if (priceObj != null) {
    30.             String priceStr = priceObj.toString();
    31.             Double price = 0d;
    32.             try {
    33.                 price = Double.parseDouble(priceStr);
    34.             } catch (Exception e) {
    35.             }
    36.             b1 = price > 50d;
    37.         }
    38.         boolean b2 = false;
    39.         Object sizes = map.getOrDefault("sizes", null);
    40.         if (sizes != null && sizes instanceof List) {
    41.             List<String> sizeList = (List<String>) sizes;
    42.             List<String> targetList = Arrays.asList("M");
    43.             for (String size : sizeList) {
    44.                 if (targetList.contains(size)) {
    45.                     b2 = true;
    46.                     break;
    47.                 }
    48.             }
    49.         }
    50.         return b1 || b2;
    51.     };
    52.     // 使用谓词的占位符?
    53.     Clothes[] clothes3 = ctx.read("$.store.clothes[?]", Clothes[].class, rule);
    54.     System.out.println("-------------- clothes3 ---------------");
    55.     for (Clothes clothes : clothes3) {
    56.         System.out.println(clothes);
    57.     }
    58. }
    复制代码
    1. ************** clothes1 ***************
    2. Clothes{name='牛仔裤', price=94.0, sizes=S}
    3. Clothes{name='裙子', price=1.24, sizes=[S, M]}
    4. Clothes{name='羊毛衫', price=78.99, sizes=[XS, XL]}
    5. Clothes{name='Polo衫', price=18.99, sizes=[XS, XL, M]}
    6. ************** clothes2 ***************
    7. Clothes{name='牛仔裤', price=94.0, sizes=S}
    8. Clothes{name='裙子', price=1.24, sizes=[S, M]}
    9. Clothes{name='羊毛衫', price=78.99, sizes=[XS, XL]}
    10. Clothes{name='Polo衫', price=18.99, sizes=[XS, XL, M]}
    11. -------------- clothes3 ---------------
    12. Clothes{name='牛仔裤', price=94.0, sizes=S}
    13. Clothes{name='裙子', price=1.24, sizes=[S, M]}
    14. Clothes{name='羊毛衫', price=78.99, sizes=[XS, XL]}
    15. Clothes{name='Polo衫', price=18.99, sizes=[XS, XL, M]}
    复制代码
    3.5、使用函数

    1. //language=JSON
    2. String jsonStr = "{\n" +
    3.         "  "name": "tom",\n" +
    4.         "  "age": 18,\n" +
    5.         "  "height": 1.77,\n" +
    6.         "  "scores": [1.1, 2.2, 3,3, 4.4, 5.5, 6.6]\n" +
    7.         "}";
    8. ReadContext ctx = JsonPath.using(Configuration.defaultConfiguration()).parse(jsonStr);
    9. Double min = ctx.read("$.scores.min()");
    10. System.out.println(min);//1.1
    11. Double max = ctx.read("$.scores.max()");
    12. System.out.println(max);//6.6
    13. Double avg = ctx.read("$.scores.avg()");
    14. System.out.println(avg);//3.6857142857142864
    15. Double stddev = ctx.read("$.scores.stddev()");
    16. System.out.println(stddev);//1.7779832647682354
    17. Double sum = ctx.read("$.scores.sum()");
    18. System.out.println(sum);//25.800000000000004
    19. Integer length = ctx.read("$.scores.length()");
    20. System.out.println(length);//7
    21. Set<String> keys = ctx.read("$.keys()");
    22. System.out.println(keys);//[name, age, height, scores]
    23. String concat = ctx.read("$.concat(@.name, " ", @.age)");
    24. System.out.println(concat);//tom 18
    25. List<Double> scores = ctx.read("$.scores.append(99.9)");
    26. System.out.println(scores);//[1.1,2.2,3,3,4.4,5.5,6.6,99.9]
    复制代码
    3.6、返回路径

    JsonPath 可以返回 Path 或 Value。Value 是默认值,也是上面所有示例的返回值。如果你更希望得到我们的查询所命中的元素的路径,这可以通过一个选项来实现。
    1. //返回路径
    2. Configuration configuration = Configuration
    3.         .builder()
    4.         .options(Option.AS_PATH_LIST)
    5.         .build();
    6. List<String> pathList = JsonPath.using(configuration).parse(jsonStr).read("$..author");
    7. System.out.println(pathList);
    8. //["$['store']['book'][0]['author']",
    9. // "$['store']['book'][1]['author']",
    10. // "$['store']['book'][2]['author']","
    11. // $['store']['book'][3]['author']"]
    复制代码
    3.7、添加/设置值

    1. String str = "{"name": "tom"}";
    2. //设置值
    3. String newStr1 = JsonPath.parse(str)
    4.         .set("$.name", "jerry")
    5.         .jsonString();
    6. //添加
    7. String newStr2 = JsonPath.parse(newStr1)
    8.         .put("$", "age",17)
    9.         .jsonString();
    10. //{"name":"jerry","age":17}
    11. System.out.println(newStr2);
    复制代码
    3.8、配置

    1)、Options

    有几个选项标志可以改变JsonPath的默认行为:

    1. @Test
    2. public void configTest1() {
    3.     //language=JSON
    4.     String jsonStr = "[\n" +
    5.             "  {\n" +
    6.             "    "name" : "john",\n" +
    7.             "    "gender" : "male"\n" +
    8.             "  },\n" +
    9.             "  {\n" +
    10.             "    "name" : "ben"\n" +
    11.             "  }\n" +
    12.             "]";
    13.     //默认情况抛出异常
    14.     //com.jayway.jsonpath.PathNotFoundException: No results for path: $[1]['gender']
    15.     String gender1 = JsonPath.parse(jsonStr).read("$[1].gender");
    16.     //使用DEFAULT_PATH_LEAF_TO_NULL,会返回Null
    17.     Configuration configuration = Configuration.builder()
    18.             .options(Option.DEFAULT_PATH_LEAF_TO_NULL)
    19.             .build();
    20.     String gender2 = JsonPath.using(configuration).parse(jsonStr).read("$[1].gender");
    21.     System.out.println(gender2);//null
    22. }
    复制代码

    1. @Test
    2. public void configTest2() {
    3.     String jsonStr = "[\n" +
    4.             "  {\n" +
    5.             "    "name" : "john",\n" +
    6.             "    "gender" : "male"\n" +
    7.             "  },\n" +
    8.             "  {\n" +
    9.             "    "name" : "ben"\n" +
    10.             "  }\n" +
    11.             "]";
    12.     //默认情况下抛出异常
    13.     //java.lang.ClassCastException: java.lang.String cannot be cast to java.util.List
    14.     List<String> genders1 = JsonPath.parse(jsonStr).read("$[0].gender");
    15.     //使用ALWAYS_RETURN_LIST,返回一个列表
    16.     Configuration configuration = Configuration.builder()
    17.             .options(Option.ALWAYS_RETURN_LIST)
    18.             .build();
    19.     List<String> genders2 = JsonPath.using(configuration).parse(jsonStr).read("$[0].gender");
    20.     System.out.println(genders2);//["male"]
    21. }
    复制代码

    1. @Test
    2. public void configTest3() {
    3.     String jsonStr = "[\n" +
    4.             "  {\n" +
    5.             "    "name" : "john",\n" +
    6.             "    "gender" : "male"\n" +
    7.             "  },\n" +
    8.             "  {\n" +
    9.             "    "name" : "ben"\n" +
    10.             "  }\n" +
    11.             "]";
    12.     //存在 ALWAYS_RETURN_LIST选项,则返回空列表
    13.     Configuration configuration1 = Configuration.builder()
    14.             .options(Option.ALWAYS_RETURN_LIST, Option.SUPPRESS_EXCEPTIONS)
    15.             .build();
    16.     List<String> genders1 = JsonPath.using(configuration1).parse(jsonStr).read("$[1].gender");
    17.     System.out.println(genders1);//[]
    18.     //不存在 ALWAYS_RETURN_LIST选项,则返回Null
    19.     Configuration configuration2 = Configuration.builder()
    20.             .options(Option.SUPPRESS_EXCEPTIONS)
    21.             .build();
    22.     List<String> genders2 = JsonPath.using(configuration2).parse(jsonStr).read("$[1].gender");
    23.     System.out.println(genders2);//null
    24. }
    复制代码

    1. @Test
    2. public void configTest4() {
    3.     String jsonStr = "[\n" +
    4.             "  {\n" +
    5.             "    "name" : "john",\n" +
    6.             "    "gender" : "male"\n" +
    7.             "  },\n" +
    8.             "  {\n" +
    9.             "    "name" : "ben"\n" +
    10.             "  }\n" +
    11.             "]";
    12.     //存在 REQUIRE_PROPERTIES,则抛出异常
    13.     //com.jayway.jsonpath.PathNotFoundException: No results for path: $[1]['gender']
    14.     Configuration configuration1 = Configuration.builder()
    15.             .options(Option.REQUIRE_PROPERTIES)
    16.             .build();
    17.     // List<String> genders1 = JsonPath.using(configuration1).parse(jsonStr).read("$[*].gender");
    18.     //不存在 REQUIRE_PROPERTIES,返回["male"]
    19.     Configuration configuration2 = Configuration.builder()
    20.             .options()
    21.             .build();
    22.     List<String> genders2 = JsonPath.using(configuration2).parse(jsonStr).read("$[*].gender");
    23.     System.out.println(genders2);//["male"]
    24. }
    复制代码

    2)、JsonProvider SPI

    JsonPath 提供五种差别的 JsonProviders:

    只有在应用程序初始化时,才气按演示更改配置默认值。强烈不发起在运行期间更改配置,尤其是在多线程应用程序中。
    1. Configuration.setDefaults(new Configuration.Defaults() {
    2.     private final JsonProvider jsonProvider = new JacksonJsonProvider();
    3.     private final MappingProvider mappingProvider = new JacksonMappingProvider();
    4.       
    5.     @Override
    6.     public JsonProvider jsonProvider() {
    7.         return jsonProvider;
    8.     }
    9.     @Override
    10.     public MappingProvider mappingProvider() {
    11.         return mappingProvider;
    12.     }
    13.    
    14.     @Override
    15.     public Set<Option> options() {
    16.         return EnumSet.noneOf(Option.class);
    17.     }
    18. });
    复制代码
    请注意,JacksonJsonProvider 必要 com.fasterxml.jackson.core:jackson-databind:2.4.5 的类路径,而 GsonJsonProvider 必要 com.google.code.gson:gson:2.3.1 的类路径。
    Jakarta EE 9 JSON-P (JSR-342) 和 JSON-B (JSR-367) 提供程序至少必要 Java 8,并要求应用程序运行时类路径上有兼容的 JSON API 实现(如 Eclipse Glassfish 和 Eclipse Yasson);Java EE 应用程序容器也大概提供此类实现。还请注意,Apache Johnzon 尚不兼容 Jakarta EE 9 规范的类路径,如果选择 JSON-B 映射提供程序,则还必须配置和使用 JSON-P 提供程序。
    Jakarta EE 9 关于 JSON 处置惩罚和数据库绑定(映射)的规范有一个特点,即 Json 数组和对象在完全解析或写入后具有不变性。为了服从 API 规范,同时答应 JsonPath 通过添加、设置/输入、替换和删除操纵来修改 Json 文档,JakartaJsonProvider 必须使用可选的 true 参数进行 initiliazed:

    无论采取哪种启动模式,都支持使用 JsonPath 进行的所有查找和读取操纵。默认模式所需的内存更少,性能更高。
    3)、Cache SPI

    JsonPath 2.1.0 引入了新的缓存 SPI。这答应 API 用户根据本身的必要配置路径缓存。缓存必须在首次访问前配置好,否则会产生 JsonPathException 异常。JsonPath 有两种缓存实现

    如果您想实现本身的缓存,API 也很简朴:
    1. CacheProvider.setCache(new Cache() {
    2.     //Not thread safe simple cache
    3.     private Map<String, JsonPath> map = new HashMap<String, JsonPath>();
    4.     @Override
    5.     public JsonPath get(String key) {
    6.         return map.get(key);
    7.     }
    8.     @Override
    9.     public void put(String key, JsonPath jsonPath) {
    10.         map.put(key, jsonPath);
    11.     }
    12. });
    复制代码
    免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




    欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4