JSONパス構文コメント(ジャワ)

Jayway JsonPath

JSON文書を読み取るためのJava DSL。

ステータスを構築
Mavenの中央
Javadocの

Jayway JsonPathはのJavaのポートであるステファンGoessner JsonPath実装

ニュース

2017年7月5日 - JsonPath 2.4.0リリース

2017年6月26日 - JsonPath 2.3.0リリース

2016年2月29日 - JsonPath 2.2.0リリース

2015年11月22日 - JsonPath 2.1.0リリース

2015年3月19日 - JsonPath 2.0.0リリース

2014年11月11日 - JsonPath 1.2.0リリース

2014年10月1日 - JsonPath 1.1.0リリース

2014年9月26日 - JsonPath 1.0.0リリース

入門

JsonPathは、中央Mavenのリポジトリから入手可能です。MavenのユーザーがあなたのPOMにこれを追加します。

<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.3.0</version>
</dependency>

あなたはで質問を助けが必要な場合は、スタックオーバーフロー質問「jsonpath」と「javaの」タグ。

JsonPath式は常に組み合わせて使用されるXPath式と同じようにJSON構造を参照
するXMLドキュメントで。JsonPathにおける「ルート・メンバオブジェクトは、」いつものように呼ばれている$にかかわらず、それがある場合
、オブジェクトまたは配列。

JsonPath式は、ドット表記を使用することができます

$.store.book[0].title

またはブラケット記法

$['store']['book'][0]['title']

演算子

オペレーター 説明
$ 照会するルート要素。これは、すべてのパス式を開始します。
@ フィルタ述語によって処理されている現在のノード。
* ワイルドカード。利用可能な任意の場所に名前や数字が必要です。
.. ディープスキャン。利用可能な任意の場所に名前が必要です。
.<name> ドット表記子
['<name>' (, '<name>')] ブラケット表記の子供や子供
[<number> (, <number>)] 配列のインデックスまたはインデックス
[start:end] 配列スライス演算子
[?(<expression>)] 式をフィルタリングします。式はブール値に評価される必要があります。

関数

機能は、パスの末尾に呼び出すことができる-関数への入力は、パス式の出力です。
関数の出力は、関数自体によって決定されます。

関数 説明 出力
(I) 数字の配列の最小値を与えます ダブル
MAX() 数字の配列の最大値を提供します ダブル
AVG() 数字のアレイの平均値を提供します ダブル
STDDEV() 数字の配列の標準偏差値を提供します ダブル
長さ() 配列の長さを提供 整数

フィルタ演算子

フィルタは、アレイをフィルタリングするために使用される論理式です。典型的なフィルタは次のようになり[?(@.age > 18)]ここで@処理されている現在の項目を表します。より複雑なフィルタは、論理演算子を使用して作成することができます&&||文字列リテラルは、単一引用符または二重引用符(で囲む必要があります[?(@.color == 'blue')][?(@.color == "blue")])。

オペレーター 説明
== 左が右に等しい(1「1」に等しくないことに留意されたいです)
!= 左は右に等しくありません
< 左は右よりも少ないです
<= 左は右に小さいか等しいです
> 左は右よりも大きいです
> = 左が右以上であり、
=〜 左が正規表現に一致[?(@。名前=〜/foo.*?/i)]
左は右に存在する[?([ 'S' で、@。サイズ、 'M'])]
インクルード 左は右に存在しません。
subsetof 左は、[(@。[ 'S'、 'M'、 'L'] subsetofサイズ)?]権利のサブセットであります
サイズ 左(配列または文字列)の大きさは、右一致する必要があります
空の 左(配列または文字列)が空でなければなりません

パスの例

JSONを考えます

{
    "store": {
        "book": [
            {
                "category": "reference",
                "author": "Nigel Rees",
                "title": "Sayings of the Century",
                "price": 8.95
            },
            {
                "category": "fiction",
                "author": "Evelyn Waugh",
                "title": "Sword of Honour",
                "price": 12.99
            },
            {
                "category": "fiction",
                "author": "Herman Melville",
                "title": "Moby Dick",
                "isbn": "0-553-21311-3",
                "price": 8.99
            },
            {
                "category": "fiction",
                "author": "J. R. R. Tolkien",
                "title": "The Lord of the Rings",
                "isbn": "0-395-19395-8",
                "price": 22.99
            }
        ],
        "bicycle": {
            "color": "red",
            "price": 19.95
        }
    },
    "expensive": 10
}
JsonPath(しようとするリンクをクリックしてください) 結果
$ .store.book [*]。著者 すべての書籍の著者
$ ..著者 すべての著者
$ .store。* すべてのもの、書籍や自転車の両方
$ .store..price すべての価格
$ ..ブック[2] 第三の本
$ ..ブック[-2] 最後の本に2番目
$ ..ブック[0,1] The first two books
$..book[:2] All books from index 0 (inclusive) until index 2 (exclusive)
$..book[1:2] All books from index 1 (inclusive) until index 2 (exclusive)
$..book[-2:] Last two books
$..book[2:] Book number two from tail
$..book[?(@.isbn)] All books with an ISBN number
$.store.book[?(@.price < 10)] All books in store cheaper than 10
$..book[?(@.price <= $['expensive'])] All books in store that are not "expensive"
$..book[?(@.author =~ /.*REES/i)] All books matching regex (ignore case)
$..* Give me every thing
$..book.length() The number of books

Reading a Document

The simplest most straight forward way to use JsonPath is via the static read API.

String json = "...";

List<String> authors = JsonPath.read(json, "$.store.book[*].author");

If you only want to read once this is OK. In case you need to read an other path as well this is not the way
to go since the document will be parsed every time you call JsonPath.read(...). To avoid the problem you can
parse the json first.

String json = "...";
Object document = Configuration.defaultConfiguration().jsonProvider().parse(json);

String author0 = JsonPath.read(document, "$.store.book[0].author");
String author1 = JsonPath.read(document, "$.store.book[1].author");

JsonPath also provides a fluent API. This is also the most flexible one.

String json = "...";

ReadContext ctx = JsonPath.parse(json);

List<String> authorsOfBooksWithISBN = ctx.read("$.store.book[?(@.isbn)].author");


List<Map<String, Object>> expensiveBooks = JsonPath
                            .using(configuration)
                            .parse(json)
                            .read("$.store.book[?(@.price > 10)]", List.class);

What is Returned When?

When using JsonPath in java its important to know what type you expect in your result. JsonPath will automatically
try to cast the result to the type expected by the invoker.

//Will throw an java.lang.ClassCastException    
List<String> list = JsonPath.parse(json).read("$.store.book[0].author")

//Works fine
String author = JsonPath.parse(json).read("$.store.book[0].author")

When evaluating a path you need to understand the concept of when a path is definite. A path is indefinite if it contains:

  • .. - a deep scan operator
  • ?(<expression>) - an expression
  • [<number>, <number> (, <number>)] - multiple array indexes

Indefinite paths always returns a list (as represented by current JsonProvider).

By default a simple object mapper is provided by the MappingProvider SPI. This allows you to specify the return type you want and the MappingProvider will
try to perform the mapping. In the example below mapping between Long and Date is demonstrated.

String json = "{\"date_as_long\" : 1411455611975}";

Date date = JsonPath.parse(json).read("$['date_as_long']", Date.class);

If you configure JsonPath to use JacksonMappingProvider or GsonMappingProvider` you can even map your JsonPath output directly into POJO's.

Book book = JsonPath.parse(json).read("$.store.book[0]", Book.class);

To obtainin full generics type information, use TypeRef.

TypeRef<List<String>> typeRef = new TypeRef<List<String>>() {};

List<String> titles = JsonPath.parse(JSON_DOCUMENT).read("$.store.book[*].title", typeRef);

Predicates

There are three different ways to create filter predicates in JsonPath.

Inline Predicates

Inline predicates are the ones defined in the path.

List<Map<String, Object>> books =  JsonPath.parse(json)
                                     .read("$.store.book[?(@.price < 10)]");

You can use && and || to combine multiple predicates [?(@.price < 10 && @.category == 'fiction')] ,
[?(@.category == 'reference' || @.price > 10)].

You can use ! to negate a predicate [?(!(@.price < 10 && @.category == 'fiction'))].

Filter Predicates

Predicates can be built using the Filter API as shown below:

import static com.jayway.jsonpath.JsonPath.parse;
import static com.jayway.jsonpath.Criteria.where;
import static com.jayway.jsonpath.Filter.filter;
...
...

Filter cheapFictionFilter = filter(
   where("category").is("fiction").and("price").lte(10D)
);

List<Map<String, Object>> books =  
   parse(json).read("$.store.book[?]", cheapFictionFilter);

Notice the placeholder ? for the filter in the path. When multiple filters are provided they are applied in order where the number of placeholders must match
the number of provided filters. You can specify multiple predicate placeholders in one filter operation [?, ?], both predicates must match.

Filters can also be combined with 'OR' and 'AND'

Filter fooOrBar = filter(
   where("foo").exists(true)).or(where("bar").exists(true)
);
   
Filter fooAndBar = filter(
   where("foo").exists(true)).and(where("bar").exists(true)
);

Roll Your Own

Third option is to implement your own predicates

Predicate booksWithISBN = new Predicate() {
    @Override
    public boolean apply(PredicateContext ctx) {
        return ctx.item(Map.class).containsKey("isbn");
    }
};

List<Map<String, Object>> books = 
   reader.read("$.store.book[?].isbn", List.class, booksWithISBN);

Path vs Value

In the Goessner implementation a JsonPath can return either Path or Value. Value is the default and what all the examples above are returning. If you rather have the path of the elements our query is hitting this can be acheived with an option.

Configuration conf = Configuration.builder()
   .options(Option.AS_PATH_LIST).build();

List<String> pathList = using(conf).parse(json).read("$..author");

assertThat(pathList).containsExactly(
    "$['store']['book'][0]['author']",
    "$['store']['book'][1]['author']",
    "$['store']['book'][2]['author']",
    "$['store']['book'][3]['author']");

Tweaking Configuration

Options

When creating your Configuration there are a few option flags that can alter the default behaviour.

DEFAULT_PATH_LEAF_TO_NULL


This option makes JsonPath return null for missing leafs. Consider the following json

[
   {
      "name" : "john",
      "gender" : "male"
   },
   {
      "name" : "ben"
   }
]
Configuration conf = Configuration.defaultConfiguration();

//Works fine
String gender0 = JsonPath.using(conf).parse(json).read("$[0]['gender']");
//PathNotFoundException thrown
String gender1 = JsonPath.using(conf).parse(json).read("$[1]['gender']");

Configuration conf2 = conf.addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL);

//Works fine
String gender0 = JsonPath.using(conf2).parse(json).read("$[0]['gender']");
//Works fine (null is returned)
String gender1 = JsonPath.using(conf2).parse(json).read("$[1]['gender']");

ALWAYS_RETURN_LIST


This option configures JsonPath to return a list even when the path is definite.

Configuration conf = Configuration.defaultConfiguration();

//Works fine
List<String> genders0 = JsonPath.using(conf).parse(json).read("$[0]['gender']");
//PathNotFoundException thrown
List<String> genders1 = JsonPath.using(conf).parse(json).read("$[1]['gender']");

SUPPRESS_EXCEPTIONS


This option makes sure no exceptions are propagated from path evaluation. It follows these simple rules:

  • If option ALWAYS_RETURN_LIST is present an empty list will be returned
  • If option ALWAYS_RETURN_LIST is NOT present null returned

JsonProvider SPI

JsonPath is shipped with three different JsonProviders:

アプリケーションが初期化されている場合にのみ行われるべきで示されたような構成のデフォルトを変更します。実行時に変更が強く、特にマルチスレッドアプリケーションでは、お勧めしません。

Configuration.setDefaults(new Configuration.Defaults() {

    private final JsonProvider jsonProvider = new JacksonJsonProvider();
    private final MappingProvider mappingProvider = new JacksonMappingProvider();
      
    @Override
    public JsonProvider jsonProvider() {
        return jsonProvider;
    }

    @Override
    public MappingProvider mappingProvider() {
        return mappingProvider;
    }
    
    @Override
    public Set<Option> options() {
        return EnumSet.noneOf(Option.class);
    }
});

JacksonJsonProviderが必要であることに注意com.fasterxml.jackson.core:jackson-databind:2.4.5してGsonJsonProviderが必要ですcom.google.code.gson:gson:2.3.1あなたのクラスパスに。

キャッシュSPI

JsonPath 2.1.0では、新たなキャッシュSPIが導入されました。これは、APIの消費者が自分のニーズに合った方法でパスキャッシングを設定することができます。それが最初にアクセスされる前にキャッシュを設定する必要がありますかJsonPathExceptionがスローされます。2つのキャッシュ実装とJsonPath船

  • com.jayway.jsonpath.spi.cache.LRUCache (デフォルトでは、スレッドセーフです)
  • com.jayway.jsonpath.spi.cache.NOOPCache (キャッシュされません)

あなたがあなた自身のキャッシュを実装する場合は、APIは簡単です。

CacheProvider.setCache(new Cache() {
    //Not thread safe simple cache
    private Map<String, JsonPath> map = new HashMap<String, JsonPath>();

    @Override
    public JsonPath get(String key) {
        return map.get(key);
    }

    @Override
    public void put(String key, JsonPath jsonPath) {
        map.put(key, jsonPath);
    }
});

解析

おすすめ

転載: www.cnblogs.com/yanximin/p/10984006.html