(0)目次&概説
(1) 記事の目的
(1-1) 目的
(2) JSON形式の概要
(2-1) JSON形式とは?
(2-2) JSON形式のフォーマット
(3) JSON形式の抽出方法・事前準備
(3-1) JSON形式の抽出ルール
(3-2) JSON in Javaライブラリ追加の手順
(3-3) JSONの抽出構文
(4) JSON抽出プログラム実装例
(4-1) サンプルプログラム
(4-2) 実行結果
(5) JSON配列の抽出について
(6) エラー対応
(6-1) エラー1:java.lang.NoClassDefFoundError
(6-2) エラー2:java.lang.ClassNotFoundException
(1) 記事の目的
(1-1) 目的
この記事の目的はJSON形式のデータをJavaで抽出するために必要な「前準備」と、実施の「サンプルコード」を紹介する事です。
(2) JSON形式の概要
(2-1) JSON形式とは?
(2-2) JSON形式のフォーマット
・{ }で全体を括っています。
・「名前」と「値」をペアにしていて「名前」は「key」と呼び「値」は「value」と呼びます。
・各keyと値はダブルクォーテーション「”」で括ります。
・ペアとペアの間はカンマで区切ります。
(例)
//### 形式の例
{
"[名前]" : "[値]"
,"[名前]" : "[値]"
,"[名前]" : "[値]"
}
//### 実際の例
{
"address1": "東京都",
"address2": "新宿区",
"address3": "新小川町",
"kana1": "トウキョウト",
"kana2": "シンジュクク",
"kana3": "シンオガワマチ",
"prefcode": "13",
"zipcode": "1620814"
}
(3) JSON形式の抽出方法・事前準備
(3-1) JSON形式の抽出ルール
(3-2) JSON in Javaライブラリ追加の手順
(3-2-1) ライブラリのダウンロード
①下記URLにアクセスして、中央付近のHomePageのリンクをクリックするとGitHubeのページに遷移します。
https://mvnrepository.com/artifact/org.json/json/20180813
(図411)①

②「JSON in Java [package org.json]」と書かれた部分の上部に「Click here if you just want~」のリンクがあるので、ここをクリックするとjarファイル「json-yyymmdd.jar」のダウンロードが始まります。
https://github.com/stleary/JSON-java
(図411)②

(3-2-2) サーバへのアップロード
TeraTerm等にログインして、jarファイルをサーバにアップロードします。
(図412)

↓

(3-2-3) プロジェクトにjarファイルを追加
JSON形式を扱うJavaプロジェクトに対して、先程サーバにアップロードしたjarファイルを追加します。
①jarファイルを追加するプロジェクトを右クリックして「BuildPath」→「Configure Build Path」と選択していきます。
(図413)①

②左ペインで「Java Build Path」が選択されている事を確認し「Library」タブにて「Add External Jars」を押下して、先程サーバにアップロードしたjarファイルを選択します。
(図413)②


(3-2-4) 追加結果の確認
正常に追加できた事の確認として「org.json.JSONObject」パッケージをインポートし、JSONObjectのインスタンスが作成できるかどうかチェックします。
(図414)Before:JSONObjectクラスのインスタンスを作ろうとするとエラーになる

↓jarファイルの追加に伴いJSONObjectのエラーが解消する
(図414)After

(3-3) JSONの抽出構文
下記1行目でJSONObjectクラスのインスタンスを作り、そこから2行目のgetStringメソッドや3行目のgetIntメソッドで値を取得しています。
JSONObject json = new JSONObject(result);
System.out.println(json.getString("login"));
System.out.println(json.getInt("id"));
(4) JSON抽出プログラム実装例
(4-1) サンプルプログラム
先程の構文を実際のプログラムに当てはめてみます。ベースとなるプログラムはGitHubのAPIをコールしてユーザ情報を取得するコードを用いてJSON形式のデータを取得し、そこから各要素を上記構文で取得します。ベースプログラム(GitHubのAPIをコールする部分)については別記事で詳細に記載しています(記事:GitHubのWebAPIをコールしてユーザー情報を取得するサンプルプログラムの解説+エラー対応も2例紹介)
package studyc;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.Base64;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;
@WebServlet("/WebAPI_IT0111")
public class IT0111_ExtractJsonData extends HttpServlet {
private static final long serialVersionUID = 1L;
public IT0111_ExtractJsonData() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String url = "api.github.com/users/XXXXXXXX";
getGithubContentUsingURLConnection(request,response,url);
}
//### メソッド名称: getGithubContentUsingURLConnection
//### メソッド概要: GitHubのAPI
//### 【引数3】String token :WebAPIを利用するためのトークン
//### 【引数4】String url :WebAPIのURL
public static void getGithubContentUsingURLConnection(HttpServletRequest request, HttpServletResponse response, String url) throws IOException {
//### APIコールのためのURL組み立て
String newURL = "https://" + url;
//### InputStream型の変数を初期化
InputStream crunchifyInStream = null;
//### 変数の初期化
String result = ""; //最終結果を格納するための変数
String tmp = ""; //読み込んだデータを格納するための一時変数
try {
//### URLオブジェクトをインスタンス化
//### 【引数】newURL :APIのURL
URL myURL = new URL(newURL);
//### URLクラスのopenConnection()メソッドを使って、URLConnectionクラスをインスタンス化
URLConnection connection = myURL.openConnection();
//### Base64.getEncoder()でBasic型のエンコーダの名称を取得(リクエストヘッダーにセット)
//### 【参考1】https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html
String authString = "Basic " + Base64.getEncoder();
//### setRequestProperty()メソッドでRequest(リクエスト)のプロパティ情報(リクエストヘッダー)をセットしています。
//### 【参考1】https://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html
//### 【引数1】String key :リクエストを表現するキーワード
//### 【引数2】String value :付帯する値の情報
connection.setRequestProperty("Authorization", authString);
//### getInputStream()メソッドでURLConnectionクラスにてオープンしている接続から、データを読むInputStreamクラスのインスタンス作成
//### 【参考1】https://docs.oracle.com/javase/7/docs/api/java/net/URLConnection.html
crunchifyInStream = connection.getInputStream();
} catch (Exception e) {
e.printStackTrace();
}
//### InputStreamReaderクラスはByteストリームとCharacterストリームの橋渡しを行います。
//### InputStreamReaderクラスのコンストラクタで引数を指定していないため、デフォルトの文字コードでインスタンス化しています。
//### BufferedReaderクラスのコンストラクタを用いて、バッファリングによる最高効率の読込みを可能にしています(メモリアクセスによって読込みを行いディスクI/Oを削減する)
BufferedReader in = new BufferedReader(new InputStreamReader(crunchifyInStream));
try {
//### 行がnullでない間、1行ずつ読んでいき、最終結果のresultに追加していく
while((tmp = in.readLine())!=null) {
result += tmp;
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
//### 画面出力
//### 文字コードや出力形式の指定
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
//### 画面のHTMLに改行(<br />)を追記
out.println("<br />");
JSONObject json = new JSONObject(result);
response.getWriter().append("login : "+json.getString("login")); out.println("<br />");
response.getWriter().append("id : "+json.getInt("id")); out.println("<br />");
}
}
(4-2) 実行結果
このサーブレットを実際にウェブブラウザから訪問すると次のように、GitHubユーザの”login”要素と”id”要素がプリントされます。
(図433)

(5) JSON配列の抽出について
次のようにJSON形式が配列になって格納されているような場合は、JSONArrayという別のクラスも使って抽出する必要があります。それについては長くなるので下記の別記事にて説明いたします。
{
"results":
[
{
"address1": "東京都",
"address2": "新宿区",
"address3": "新小川町",
"zipcode": "1620814"
},
{
"address1": "神奈川県",
"address2": "横浜市",
"address3": "羽沢南",
"zipcode": "2210866"
}
],
"status": 200
}
⇒記事:JavaでJSON配列から値を抽出する方法+郵便番号検索APIのサンプルプログラムも紹介
(6) エラー対応
(6-1) エラー1:java.lang.NoClassDefFoundError
(6-1-1) エラー概要
サーブレットの実行時に下記のエラーが発生。
java.lang.NoClassDefFoundError: org/json/JSONObject
(図511)

(6-1-2) エラー原因
NoClassDefFoundErrorはJava実行時に起きる「エラー」です。一般的には、特定のクラスがコンパイル時には存在したが、実行時に存在しなかった場合に出るエラーで、JREによってエラーが報告されます。
今回のケースは正確な特定は出来ておりませんがjsonデータの抽出に用いた「json-yyyymmdd.jar」に関する「Web Deployment Assembly」や「外部jarファイルの追加」の設定を見直す事でエラーが解消しました。
(6-1-3) エラー対処
上述の通り「外部jar」と「Web Deployment Assembly」の設定を見直します。「Web Deployment Assembly」は「外部jar」の結果を反映させるため、順番としては「外部jar」が先になります。
①プロジェクトを右クリックして「BuildPath」⇒「Configure Build Path」と選択
(図513)①

②右側のメニューで「Add External Jars」を選択
(図513)②

③追加対象のjarファイルを選択して「Apply and Close」で適用
(図513)③

(b) Web Deployment Assemblyの見直し
先ほどビルドパスに追加した設定をWeb Deployment Assemblyにも反映させます。
④同じプロパティの画面の左側で「Deployment Assembly」を選択し、右側メニューの「Add」を押して「Java Build Path Entries」を選択します。
(図513)④

⑤先ほどビルドパスに追加したjarファイルを選択して追加します。
(図513)⑤

(6-1-4) Web Deployment Assemblyの補足・用語説明
(6-2) エラー2:java.lang.ClassNotFoundException
(6-2-1) エラー概要
サーブレットの実行時に下記のエラーが発生。
java.lang.ClassNotFoundException: org/json/JSONObject
(図521)※下記は例でエラーの再現例であり、実際のプログラムとは異なります。

(6-1-2) エラー原因
(6-1-3) エラー対処
jsonデータの抽出に用いた「json-yyyymmdd.jar」に関する「外部jarファイルの追加」の設定を見直す事でエラーが解消しました。
具体的な手順は「(6-1-3) エラー対処」の「(a) 外部jarの見直し」と同じです。