雑記 |
Visual Basic 中学校 > 雑記 >
2020/6/21
この記事が対象とする製品・バージョン
![]() |
Visual Studio 2019 | ◎ | 対象です。 |
![]() |
Visual Studio 2017 | ◎ | 対象です。 |
![]() |
Visual Studio 2015 | ◎ | 対象です。 |
![]() |
Visual Studio 2013 | ◎ | 対象です。 |
![]() |
Visual Studio 2012 | ◎ | 対象です。 |
![]() |
Visual Studio 2010 | ◎ | 対象です。 |
![]() |
Visual Studio 2008 | ◎ | 対象です。 |
![]() |
Visual Studio 2005 | × | 対象外です。 |
![]() |
Visual Studio 2003 | × | 対象外です。 |
![]() |
Visual Studio (2002) | × | 対象外です。 |
目次
JSONPathは文字列で記述する式で、これを利用するとJSONから値を取り出すことができます。
たとえば、aurhotが直木孝次郎であるすべての要素をとりだすということが簡単にできます。
VB/C#でJSONPathを使う場合、JSON.NET(Newtonsoft JSON)を使用するのが一般的です。
この記事ではJSON.NETを使ってJSONPathを使用する方法とJSONPathの構文・実例を紹介します。
参考
JSON.NET(Newtonsoft JSON)は、プロジェクトの種類によってははじめから使えるようになっていますが、WindowsフォームアプリケーションなどではNuGetからインストールする必要があります。
NuGetからインストールする場合 Newtonsoft.Json で検索します。かなりメジャーなパッケージなので検索しなくてもはじめから一番上に表示されているかもしれません。
プログラムでJSONパスのクエリを実行して単一の値を取得するにはJToken.SelectTokenメソッドを使用します。複数の値を取得するにはJToken.SelectTokensメソッドを使用します。
戻り値はJTokenまたはJTokenのコレクションです。取得した値が単純な文字列や数値であれば、JTokenをToStringするなどして直接値を取り出せます。
取得した値がオブジェクトの場合は、戻り値に対してさらにSelectToken(s)してJSONPathでクエリをかけることもできます。
SelectTokensで取得した場合は複数の値が該当するのでFor Each~Nextでループなどしながら取り出します。
使用例は下記の通りです。
この例ではbooks.jsonという外部のファイルからJSONを読み込みJSONPathで値を取り出します。 $.info.category の部分がJSONPathです。結果は変数 Items から取り出せます。
VB
Dim appPath
As String =
AppDomain.CurrentDomain.BaseDirectory.TrimEnd("\"c) Dim jsonText As String = System.IO.File.ReadAllText(appPath & "\books.json") Dim root As JToken = DirectCast(Newtonsoft.Json.JsonConvert.DeserializeObject(jsonText), JToken) Dim items = root.SelectTokens("$.info.category") For Each item In items Debug.WriteLine(item.ToString) Next |
C#
string appPath =
AppDomain.CurrentDomain.BaseDirectory.TrimEnd('\\'); string jsonText = System.IO.File.ReadAllText(appPath + @"\books.json"); JToken root = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonText) as JToken; var items = root.SelectTokens(@"$.info.category"); foreach(var item in items) { System.Diagnostics.Debug.WriteLine(item.ToString()); } |
JSONPathでは次の記号が使用できます。
要素 | 説明 |
---|---|
$ | ルートオブジェクトまたは配列を表します。 |
.xxx | 親オブジェクトからxxxプロパティを選択します。 |
['xxx'] | 親オブジェクトからxxxプロパティを選択します。プロパティ名にスペースなど特殊な文字を含む場合にはこの構文を使用します。 |
[n] | 配列のn番目の要素を選択します。先頭の要素は 0 です。 |
[index1, index2, ...] | 配列の複数の要素を選択します。 |
..xxx | すべての子孫のxxxプロパティを選択します。 |
* | すべての要素を選択します。たとえば、address.* は addressオブジェクトのすべてのプロパティを表します。book[*]は配列bookのすべての要素を表します。 |
[start:end] | 配列のstart番目からend番目までのすべての項目を選択します。ただし、end番目の項目自体は含みません。 |
[start:] | 配列のstart番目以降のすべての項目を選択します。 |
[:n] | 配列の先頭からn個の項目を選択します。 |
[-n:] | 配列の末尾からさかのぼってn個の項目を選択します。 |
[?(filter)] | フィルターにマッチするすべての要素を選択します。フィルターで使用できる演算子等については別表で後述します。 |
[(expression)] | 式に一致するすべての項目を選択します。 |
フィルター
要素 | 説明 |
---|---|
@ | フィルターの中で現在のノードを表します。 |
@.xxx | xxxプロパティを持っている要素にマッチします。例 [?(@.price)] |
=== | 型と値が等しい。例 [?(@.price===450)] |
== | 値が等しい。例 [?(@.color=='red')] |
!= | 等しくない。 |
> | より大きい |
>= | 以上 |
< | より小さい |
<= | 以下 |
=~ | JavaScriptの正規表現に一致する。例 [?(@.description =~ /cat.*/i)] この例は catからはじまるdescriptionにマッチします。 |
! | フィルターの成否を反転させます。例 [?(!@.price)] は priceプロパティを持っていない要素にマッチします。 ※JSON.NETでは使用できないようです。 |
&& | 条件をANDで結合します。例 [?(@.category=='fiction' && @.price < 10)] |
|| | 条件をORで結合します。例 [?(@.category=='fiction' || @.price < 10)] |
参考
https://support.smartbear.com/alertsite/docs/monitors/api/endpoint/jsonpath.html
https://goessner.net/articles/JsonPath/
以下では下記JSONを前提にさまざまなJSONPathと結果を紹介します。
実際に試すには上記で紹介しているVB/C#のサンプルのJSONPath部分を置き換えてみてください。
下記サイトはブラウザー上でJSONPathを手軽に試せるので便利です。
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$.info.category
ルートから info, categoru でたどった値を返します。
取得される値は "日本史" です。
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$.books
ルートから books でたどった値を返します。
booksの値はオブジェクトなので戻り地は JObjectになります。
ToStringメソッドで文字列として黄色い部分を取得できます。また、戻り値のJObjectに対してさらにJSONPathでクエリーをかけることもできます。
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$.books..title
ルートから books でたどった先にある全子孫の title を取得します。
『「関ヶ原」の決算書』、『古代史の人びと』、『日本の歴史』、『古代国家の成立』、『奈良の都』の5つが取得できます。
このJSONの場合 $..title と書いても同じ結果です。
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$.books[*].title
ルートから books でたどった先のオブジェクトの title を取得します。
『「関ヶ原」の決算書』と『古代史の人びと』の2つが取得できます。
『日本の歴史』や『古代国家の成立』はseries要素の下にあるので取得されません。
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$.books[0]
ルート直下の books にある1つ目の要素を取得します。
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$.books[1]
ルート直下の books にある2つ目の要素を取得します。
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$.books[2]
ルート直下の books にある3つ目の要素を取得します。
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$.books[-1:]
ルート直下の books にある最後の要素を取得します。
この例では要素が3つしかないので、結果は$.books[2]と同じです。
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$.books[0:2]
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$.books[1:2]
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$..*[?(@.price)]
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$..books[?(@.price)]
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$..[?(@.author==='直木孝次郎')]
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$..[?(@.price <= 500)]
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$..[?(@.author==='直木孝次郎' || @.title==='奈良の都')]
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "boos": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
$..[?(@.author!='直木孝次郎')]
{ "info": { "category": "日本史", "lastupdate": "2021/6/27" }, "books": [ { "title": "「関ケ原」の決算書", "author": "山本博文", "price": 880 }, { "title": "古代史の人びと", "author": "直木孝次郎" }, { "series": { "title": "日本の歴史", "books": [ { "title": "古代国家の成立", "author": "直木孝次郎", "price": 450 }, { "title": "奈良の都", "author": "青木和夫" } ] } } ] } |
Querying JSON with JSON Path
https://www.newtonsoft.com/json/help/html/QueryJsonSelectToken.htm
JSONPath Syntax
https://support.smartbear.com/alertsite/docs/monitors/api/endpoint/jsonpath.html
JSONPath XPath for JSON
https://goessner.net/articles/JsonPath/
Jayway JsonPath
https://github.com/json-path/JsonPath
JSONPath Online Evaluator