(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の見直し」と同じです。