この記事はWeb API Advent Calendar 2020の20日の投稿です。皆さんは、WebAPIから受け取ったデータを使おうとした時に「いづい」思いをしたことはありませんか? えっ「いづい」 って何よ!?と思いましたか? 説明しましょう!「いづい」とは仙台弁で「なんかしっくりこない、フィットしない」という意味でタイトルの「いづぐね?」はその疑問系です。そして「いぎなり」は、「いきなり」が訛ったもので通常の「急に」という意味ではなく「凄く、めっちゃ」という程度を示す意味となります。このふたつを覚えていれば、あなたは仙台を訪れた時、間違いなく仙台民の心を掴むことができるでしょう(笑)仙台弁を極めたい人はご当地キャラの仙台弁コケシのサイトをお勧めします。ということで、仙台在住の @kuwazzy です。
さて、仙台弁講座はほどほどにして本題に入りましょう。私は仕事柄、色々なWeb APIのレスポンスデータを分析ツールで使えるデータに変換するソフトウェア製品の開発&テクニカルサポートをしているため、そのようなJSONデータに出会うことがあります。でも「何がいづい(使いづらい)の?」と聞かれても自分の中で上手く言語化出来ずにおりましたが、本Advent Calendarの9日目 @hiiragi252 さんの記事(API設計で気をつけて欲しいこと)を読んでいたら私のなかでもやっとしていたことが言語化されていて感動しました。そこで、私もこれまでに出会ったJSONデータを振り返ってみると、Web APIのいづいJSONレスポンスにはいくつかのパターンを思い出すことが出来ました。この記事では、その中でも「繰り返しデータ」に着目していづい理由を紐解いていきたいと思います。
JSONの繰り返しデータ = 配列 のことでしょ
そうです、JSONデータは配列を使うことで繰り返しデータを表現できます。サンプルとして、customer(顧客)のJSONデータをみてみましょう。
{
"customer": [
{
"Id": "1",
"Name": "John",
"Gender":"M",
"Age": 21
},
{
"Id": "2",
"Name": "Tom",
"Gender": "M",
"age": 47
},
{
"Id": "3",
"Name": "Jane",
"Gender": "F",
"age": 34
}
]
}
このJSONデータを紐解いて見ると、以下のような顧客毎の情報が**{波括弧}**にまとまって定義されています。
{
"Id": "1",
"Name": "John",
"Gender":"M",
"Age": 21
}
この顧客毎にまとまった情報が3回繰り返し定義されており、繰り返しの範囲は**[角括弧]**で表現されます。これにより、Web APIを利用する側は、顧客毎にまとまった情報が3個含まれていると理解できます。このJSONデータを分析ツールなどで利用する場合は、DataFrame(二次元配列)やRDBのTable(表)となり以下のようなデータ構造となります。つまり、キー値(IdやName)がヘッダーとなり、値(1やJohn)が値、配列の繰り返し数がレコード数になります。
Id | Name | Gender | Age |
---|---|---|---|
1 | John | M | 21 |
2 | Tom | M | 47 |
3 | Jane | F | 34 |
「えっ、当たり前のことじゃん」と思いますよね。でも、あるんです、配列じゃない繰り返しが。そんな例をこれからみていきます。
いづい理由その壱:キー値が値になっている
以下のようなJSONデータです。
{
"customer": {
"1": {
"Name": "John",
"Gender": "M",
"Age": 21
},
"2": {
"Name": "Tom",
"Gender": "M",
"age": 47
},
"3": {
"Name": "Jane",
"Gender": "F",
"age": 34
}
}
}
皆さん、どこが違うか気がつきましたか?一つの顧客を抽出してみてみましょう。
"1": {
"Name": "John",
"Gender": "M",
"Age": 21
}
キー値(コロンの左側)が顧客Idとなっています。更に繰り返し(っぽい)のに配列を使わずに表現できてしまっています。このJSONデータはVlidatorでチェックしても有効です。しかし、このJSONデータをDataFrame(二次元配列)やRDBのTable(表)にストレートに変換してみたらどうなるでしょうか?キー値(コロンの左側)をヘッダーにすると以下のようなデータ構造となります。
1.Name | 1.Gender | 1.Age | 2.Name | 2.Gender | 2.Age | 3.Name | 3.Gender | 3.Age |
---|---|---|---|---|---|---|---|---|
John | M | 21 | Tom | M | 47 | Jane | F | 34 |
このJSONデータの例では3顧客しかいませんでしたが、実際には顧客数が増えるとその分、列が増えるのでこの形式では現実的ではないでしょう。
いづい理由その弍:要素が離れている
JSONデータのサンプルをみるまでは何のことを言っているかわからないと思います。以下のようなJSONデータです。
{
"customer": {
"Id": {
"0": "1",
"1": "2",
"2": "3"
},
"Name": {
"0": "John",
"1": "Tom",
"2": "Jane"
},
"Gender": {
"0": "M",
"1": "M",
"2": "F"
},
"Age": {
"0":21,
"1": 47,
"2": 34
}
}
}
おおっと、そうきたか!と思ってしまう、このデータも構造的には有効です。このケースの場合も繰り返しは配列の印である**[角括弧]**なく定義できてしまっています。このJSONデータをDataFrame(二次元配列)やRDBのTable(表)にストレートに変換した場合、以下のような構造になります。この構造もちょっとデータ分析などでは使いづらいですね。。。
Id.0 | Id.1 | Id.2 | Name.0 | Name.1 | Name.2 | Gender.0 | Gender.1 | Gender.2 | Age.0 | Age.1 | Age.2 |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 2 | 3 | John | Tom | Jane | M | M | F | 21 | 47 | 34 |
このWeb APIは、リクエストパラメータに出力項目(outputitems)が指定できるようになっていました。
outputitems = "Id, Name"
上記のパラメータで絞り込むと以下のようなIdとNameだけのアイテムがレスポンスとして返ってきます。Web APIのサーバーサイドのアーキテクチャとしてKeyValue型や列指向のデータベースを使っているのでこういう構造になるのかもしれません。
{
"customer": {
"Id": {
"0": 1,
"1": 2,
"2": 3
},
"Name": {
"0": "John",
"1": "Tom",
"2": "Jane"
}
}
}
まとめ
本記事では、シンプルな例で説明しましたが、実際には、部分的には配列([角括弧])を使っているけど、ネストされた一部にこのような構造の繰り返しが潜んでいたりします。もう一つ「このWeb APIのレスポンスデータいぎなりいづぐね!?」の重要な要素として「深ーい、多階層のネスト(入れ子)」があります。この多階層のネストについては、またの機会にポストしたいと思います。