【Java】YahooAPIの商品検索を実装してみた

#はじめに
YahooのAPIを使ってECサイト的なものを作ってみようとしたのですが、使い方が全然分からない...という状況に陥りました。
調べてもよく分からず、かなり手こずったのでメモの意味を含めて記録に残そうと思います。

ちなみに、筆者はJavaを学んで3ヶ月くらいです。

#実現したいこと
1. HTMLのフォームから検索キーワードを受け取る
2. 検索キーワードをAPIにリクエストで渡す
3. APIから商品情報のJSONをレスポンスで受け取る
4. JSONから要素を取り出し、JavaBeansにセット
5. JavaBeansをArrayListに格納
6. ArrayListをリクエストスコープに格納し、結果出力用のjspにフォワード

#コードを書いてみた
### 検索キーワードをAPIにリクエストで渡す
どうやらAPIにリクエストを送る方法は、 URLにコネクションをすれば良いようで、
そのためのクラスがありました。
それが**HttpURLConnectionクラス**というやつです。

基本的なステップは

1. API接続用のURLを取得
2. コネクションを取得
3. 接続設定
4. 接続

といった感じです。


- [URLConnection(HttpURLConnection)と向き合おう~GETメソッドでデータを取得する~](http://blog.officekoma.co.jp/2016/07/urlconnectionhttpurlconnectionget.html)

```Java
  //アプリケーションID
  String appid = "アプリケーションID";
  //商品キーワードを受け取りString型に格納
  request.setCharacterEncoding("UTF-8");
  String query = request.getParameter("searchVal");
  //リクエストURL
  String url = "https://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch?appid="+appid+"&query="+query;
  //API接続用のURL生成
  URL url4conn = new URL(url);
  //API接続用のURLへのコネクションを取得
  HttpURLConnection conn = (HttpURLConnection)url4conn.openConnection();
  //HTTPのメソッドをGETに指定
  conn.setRequestMethod("GET");
  //リクエストのボディ送信を許可しない
  conn.setDoOutput(false);
  //レスポンスのボディ送信を許可する
  conn.setDoInput(true);
  //接続
  conn.connect();
```

###APIから商品情報のJSONをレスポンスで受け取る
どうやらAPIからレスポンスを取得するには、BufferedReaderを使ってレスポンスを読み出せば良いようです。
ただ、読み出す段階で取得できるのは**JASON文字列**なので、それをライブラリを用いて**JASONノード(JSON用の型)に変換**してあげる必要があります。

基本的なステップは、

1. レスポンスの読み出し
2. JSON文字列をJSONノードに変換

といった感じです。

 ```Java
  //レスポンスの読み出し(JASON文字列の取得)
  BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
  String json = br.readLine();
            
  //JSON文字列を読み込み、JsonNodeオブジェクトに変換
  ObjectMapper mapper = new ObjectMapper();
  JsonNode root = mapper.readTree(json);
```

###JSONから要素を取り出し、JavaBeansにセット

基本的なステップは、

1. **JSONノードから特定の要素を取り出し**、String型に格納
2. それをJavaBeansにセット

といった感じです。

JSONノードから特定の要素を取り出すには、**JsonNode.get( )**を使います。

- [Java 向け JSON ライブラリ Jackson でデータを読み込む
](https://blog.kymmt.com/entry/jackson)

```Java
  //商品検索結果の入ったBeansを格納するArrayListを生成
            ArrayList<productDataBeans> pdbList = new ArrayList<productDataBeans>();
            
  //JSONから10件分の要素を取り出し、String型に格納
  //それをBeansにセットし、BeansをArrayListに格納
  for(int i = 0; i <= 9; i++) {
        String hitNum = String.valueOf(i);
        String imageURL = root.get("ResultSet").get("0").get("Result").get(hitNum).get("Image").get("Small").textValue();
        String productName = root.get("ResultSet").get("0").get("Result").get(hitNum).get("Name").textValue();
        String price = root.get("ResultSet").get("0").get("Result").get(hitNum).get("Price").get("_value").textValue();
        int SearchResultNum = root.get("ResultSet").get("totalResultsAvailable").asInt();
                
        //商品検索結果を格納するBeansのインスタンスを生成
        productDataBeans pdb = new productDataBeans();
        pdb.setImageURL(imageURL);
        pdb.setProductName(productName);
        pdb.setPrice(price);  
                
        pdb.setQuery(query);
        pdb.setSearchResultNum(SearchResultNum);
                
        pdbList.add(pdb);
   }
            
  //ArrayListをリクエストスコープに格納
  request.setAttribute("resultData", pdbList);

  br.close();
            
  request.getRequestDispatcher("/search.jsp").forward(request, response);

```

#補足 - JSONのライブラリについて
読み出したJSON文字列はJSONノードに変換してあげる必要があるとお話しましたが、そのためにはJacksonの場合、3つのライブラリが必要になります。

 ・[jackson-core](https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core)
・[jackson-annotations](https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations)
・[jackson-databind](https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind)

リンク先のVersionを選び、bundleボタンを押すとダウンロードできます。