24
32

More than 5 years have passed since last update.

JavaでJSONをPOSTする方法 ~OkHttp3を使った方法とHttpUrlConnectionを使った方法~

Last updated at Posted at 2019-04-21

概要

JavaでJSONをHTTP POSTしたりHTTP GETしたりする方法をまとめます。
JavaでJSON→Java、Java→JSON するやり方については前稿でまとめています

  • 【本稿】JavaでHTTP通信でJSONをPOSTしたり、GETする方法についてまとめます

    • JavaでHTTP通信をするやり方も2通り説明します
      • OkHttp3を使ったやり方
      • Java標準パッケージであるHttpUrlConnectionを使ったやり方
  • 【前稿】JavaでJSONを扱う方法についてまとめます

    • JSONをJavaに変換(デシリアライズ)、JavaをJSONに変換(シリアライズ)するやり方は2通り説明します
      • ライブラリにGSONを使うやり方
      • ライブラリにJacksonを使うやり方

準備

HTTP通信をする前にJava→JSON(シリアライズ)やJSON→Java(デシリアライズ)ができるようにする必要がある。
それをお手軽にやる方法は、こちらの記事にまとめているので、ここではスキップする。

サーバーからGETしたり、サーバーにPOSTするJSONは以下の形式としてコードを考える。

サンプルのJSON文字列:example.json
{
    "person": {
        "firstName": "John",
        "lastName": "Doe",
        "address": "NewYork",
        "pets": [
            {"type": "Dog", "name": "Jolly"},
            {"type": "Cat", "name": "Grizabella"},
            {"type": "Fish", "name": "Nimo"}
        ]
    }
}

本稿では、HTTP通信するところにフォーカスする

JavaでHTTP通信する方法

2通りのアプローチを説明する

  • ライブラリ(OkHttp3)を使った方法
    HTTP通信できるライブラリはたくさんあるが、本稿では OkHttp3 をとりあげる。

  • ライブラリを使わない方法
    外部のライブラリを使わずJava標準パッケージ HttpUrlConnection を使う方法をとりあげる。

OkHttp3を使ってJSONをPOST、GETする

OkHttp3のライブラリ依存関係

OkHttp3のライブラリ指定方法は以下のとおり

■ OkHttp3の最新ライブラリ(mavenリポジトリ)
https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp

■ OkHttp3のmaven設定例

pom.xml
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.14.1</version>
</dependency>

■ OkHttp3のgradle設定例

build.gradle
compile 'com.squareup.okhttp3:okhttp:3.14.1'

OkHttp3を使ってJSONをHTTP POSTする

JSON文字列をPOSTして、結果の文字列を受け取るHTTPクライアントのサンプルは以下のとおり

OkHttpPostClient.java
/**
 * HTTPライブラリに「OkHttp3」、GSON操作ライブラリに「GSON」をつかって、
 * サーバーにJSONを「POST」するサンプル
 */
public class OkHttpPostClient {

    public static void main(String[] args) throws IOException {
        OkHttpPostClient client = new OkHttpPostClient();
        String result = client.callWebAPI();
        System.out.println(result);
    }

    private static final String WEB_API_ENDPOINT = "http://localhost:8080/api";

    public String callWebAPI() throws IOException {

        final String postJson = "{" +
                "    \"person\": {" +
                "        \"firstName\": \"John\"," +
                "        \"lastName\": \"Doe\"," +
                "        \"address\": \"NewYork\"," +
                "        \"pets\": [" +
                "            {\"type\": \"Dog\", \"name\": \"Jolly\"}," +
                "            {\"type\": \"Cat\", \"name\": \"Grizabella\"}," +
                "            {\"type\": \"Fish\", \"name\": \"Nimo\"}" +
                "        ]" +
                "    }" +
                "}";

        final Map<String, String> httpHeaders = new LinkedHashMap<String, String>();
        final String resultStr = doPost(WEB_API_ENDPOINT, "UTF-8", httpHeaders, postJson);

        return resultStr;
    }

    public String doPost(String url, String encoding, Map<String, String> headers, String jsonString) throws IOException {
        final okhttp3.MediaType mediaTypeJson = okhttp3.MediaType.parse("application/json; charset=" + encoding);

        final RequestBody requestBody = RequestBody.create(mediaTypeJson, jsonString);

        final Request request = new Request.Builder()
                .url(url)
                .headers(Headers.of(headers))
                .post(requestBody)
                .build();

        final OkHttpClient client = new OkHttpClient.Builder()
                .build();
        final Response response = client.newCall(request).execute();
        final String resultStr = response.body().string();
        return resultStr;
    }
}

OkHttp3を使ってJSONをHTTP GETする

GETするコードは以下の部分がポイントとなる。
以下ではurlとheaderを指定して、GETを実行する。
結果をテキストとして取得するには response.body().string()のようにする。

public String doGet(String url, Map<String, String> headers) throws IOException {
    final Request request = new Request.Builder()
            .url(url)
            .headers(Headers.of(headers))
            .build();
    final OkHttpClient client = new OkHttpClient.Builder().build();
    final Response response = client.newCall(request).execute();
    final String resultStr = response.body().string();
    return resultStr;
}

以下はフルソースコード。
http://localhost:8080/api にアクセスする例となる。
実験用にサーバー側のコードも下に掲載する。

OkHttpGetClient.java(ソースコード)

public class OkHttpGetClient {

    public static void main(String[] args) throws IOException {
        OkHttpGetClient client = new OkHttpGetClient();
        Model result = client.callWebAPI();
        System.out.println("Firstname is " + result.person.firstName);
    }

    private static final String WEB_API_ENDPOINT = "http://localhost:8080/api";
    private final Gson mGson = new Gson();

    public Model callWebAPI() throws IOException {
        final Map<String, String> httpHeaders = new LinkedHashMap<String, String>();
        final String resultStr = doGet(WEB_API_ENDPOINT, httpHeaders);
        final Model model = mGson.fromJson(resultStr, Model.class);
        return model;
    }

    public String doGet(String url, Map<String, String> headers) throws IOException {
        final Request request = new Request.Builder()
                .url(url)
                .headers(Headers.of(headers))
                .build();
        final OkHttpClient client = new OkHttpClient.Builder().build();
        final Response response = client.newCall(request).execute();
        final String resultStr = response.body().string();
        return resultStr;
    }

}

サーバー側のソースコード

実験用にサーバー側としてJettyをつかった簡易Web APIサーバーのコードを示す

/**
 * ・GETされると、JSON文字列を返す<br>
 * ・JSONをPOSTされると、JSONを解析して結果を返す<br>
 * HTTPサーバー
 */
public class JsonApiServer {
    public static void main(String[] args) {
        final int PORT = 8080;
        final Class<? extends Servlet> servlet = ExampleServlet.class;
        ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
        servletHandler.addServlet(new ServletHolder(servlet), "/api");

        final Server jettyServer = new Server(PORT);
        jettyServer.setHandler(servletHandler);
        try {
            jettyServer.start();
            jettyServer.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @SuppressWarnings("serial")
    public static class ExampleServlet extends HttpServlet {

        private final Gson mGson = new Gson();

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

            Model model = new Model();
            model.person = new Person();
            model.person.firstName = "ジョン";
            model.person.lastName = "ドゥ";
            model.person.address = "ニューヨーク";
            model.person.pets = new ArrayList<Pet>();
            Pet pet1 = new Pet();
            pet1.type = "犬";
            pet1.name = "ジョリー";
            model.person.pets.add(pet1);
            Pet pet2 = new Pet();
            pet2.type = "猫";
            pet2.name = "グリザベラ";
            model.person.pets.add(pet2);
            Pet pet3 = new Pet();
            pet3.type = "魚";
            pet3.name = "ニモ";
            model.person.pets.add(pet3);

            String json = mGson.toJson(model);

            resp.setContentType("text/html; charset=UTF-8");
            resp.setCharacterEncoding("UTF-8");
            final PrintWriter out = resp.getWriter();
            out.println(json);
            out.close();

        }

        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            final StringBuilder sb = new StringBuilder();
            String line = null;
            try {
                BufferedReader reader = req.getReader();
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            } catch (Exception e) {
            }
            final String body = sb.toString();
            final Model model = mGson.fromJson(body, Model.class);
            resp.setContentType("text/html; charset=UTF-8");
            resp.setCharacterEncoding("UTF-8");
            final PrintWriter out = resp.getWriter();
            out.println("Server Generated Message");
            out.println("Firstname is " + model.person.firstName);
            out.close();
        }
    }
}

ソースコード一式は以下となる
https://github.com/riversun/java-json-gson-jackson-http

HttpUrlConnectionを使ってJSONをPOST、GETする

依存ライブラリ

HttpUrlConnectionはJavaの標準パッケージなので、外部のライブラリなどは不要

ライブラリは便利で洗練されている場合も多いが、例えば、Android環境のDEXファイル64Kの壁など、多機能なライブラリ導入による依存ライブラリ数増大・総メソッド数増大を回避をしたい場合など、まだ活用の余地がある。

HttpUrlConnectionを使ってJSONをHTTP POSTする

前述した通り、Android等Javaベースの環境でも幅広く使えるよう、記法はJava1.6 Compliantとした。

UrlConnHttpPostClient.java
/**
 * HTTP通信にはJava標準の「HttpUrlConnection」、GSON操作ライブラリに「GSON」をつかって、
 * サーバーからJSONを「POST」するサンプル
 */
public class UrlConnHttpPostClient {

    public static void main(String[] args) throws IOException {
        UrlConnHttpPostClientclient = new UrlConnHttpPostClient();
        String result = client.callWebAPI();
        System.out.println(result);
    }

    private static final String WEB_API_ENDPOINT = "http://localhost:8080/api";

    public String callWebAPI() throws IOException {

        final String postJson = "{" +
                "    \"person\": {" +
                "        \"firstName\": \"John\"," +
                "        \"lastName\": \"Doe\"," +
                "        \"address\": \"NewYork\"," +
                "        \"pets\": [" +
                "            {\"type\": \"Dog\", \"name\": \"Jolly\"}," +
                "            {\"type\": \"Cat\", \"name\": \"Grizabella\"}," +
                "            {\"type\": \"Fish\", \"name\": \"Nimo\"}" +
                "        ]" +
                "    }" +
                "}";

        final Map<String, String> httpHeaders = new LinkedHashMap<String, String>();
        final String resultStr = doPost(WEB_API_ENDPOINT, "UTF-8", httpHeaders, postJson);

        return resultStr;
    }

    private String doPost(String url, String encoding, Map<String, String> headers, String jsonString) throws IOException {

        final int TIMEOUT_MILLIS = 0;// タイムアウトミリ秒:0は無限

        final StringBuffer sb = new StringBuffer("");

        HttpURLConnection httpConn = null;
        BufferedReader br = null;
        InputStream is = null;
        InputStreamReader isr = null;

        try {
            URL urlObj = new URL(url);
            httpConn = (HttpURLConnection) urlObj.openConnection();
            httpConn.setConnectTimeout(TIMEOUT_MILLIS);// 接続にかかる時間
            httpConn.setReadTimeout(TIMEOUT_MILLIS);// データの読み込みにかかる時間
            httpConn.setRequestMethod("POST");// HTTPメソッド
            httpConn.setUseCaches(false);// キャッシュ利用
            httpConn.setDoOutput(true);// リクエストのボディの送信を許可(GETのときはfalse,POSTのときはtrueにする)
            httpConn.setDoInput(true);// レスポンスのボディの受信を許可

            if (headers != null) {
                for (String key : headers.keySet()) {
                    httpConn.setRequestProperty(key, headers.get(key));// HTTPヘッダをセット
                }
            }

            final OutputStream os = httpConn.getOutputStream();
            final boolean autoFlash = true;
            final PrintStream ps = new PrintStream(os, autoFlash, encoding);
            ps.print(jsonString);
            ps.close();

            final int responseCode = httpConn.getResponseCode();

            String _responseEncoding = httpConn.getContentEncoding();
            if (_responseEncoding == null) {
                _responseEncoding = "UTF-8";
            }

            if (responseCode == HttpURLConnection.HTTP_OK) {
                is = httpConn.getInputStream();
                isr = new InputStreamReader(is, _responseEncoding);
                br = new BufferedReader(isr);
                String line = null;
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
            } else {
                // ステータスがHTTP_OK(200)以外の場合
                throw new IOException("responseCode is " + responseCode);
            }

        } catch (IOException e) {
            throw e;
        } finally {
            // Java1.6 Compliant
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                }
            }
            if (isr != null) {
                try {
                    isr.close();
                } catch (IOException e) {
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
            if (httpConn != null) {
                httpConn.disconnect();
            }
        }
        return sb.toString();
    }
}

HttpUrlConnectionを使ってJSONをHTTP GETする

UrlConnHttpGetClient.java
package com.example.http_client.urlconnection;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;

import com.example.jackson.Model;
import com.google.gson.Gson;

/**
 * HTTP通信にはJava標準の「HttpUrlConnection」、GSON操作ライブラリに「GSON」をつかって、
 * サーバーからJSONを「GET」するサンプル
 */
public class UrlConnHttpGetClient {

    public static void main(String[] args) throws IOException {
        UrlConnHttpGetClient client = new UrlConnHttpGetClient();
        Model result = client.callWebAPI();
        System.out.println("Firstname is " + result.person.firstName);
    }

    private static final String WEB_API_ENDPOINT = "http://localhost:8080/api";
    private final Gson mGson = new Gson();

    public Model callWebAPI() throws IOException {
        final Map<String, String> httpHeaders = new LinkedHashMap<String, String>();
        final String resultStr = doGet(WEB_API_ENDPOINT, httpHeaders);
        final Model model = mGson.fromJson(resultStr, Model.class);
        return model;
    }

    public String doGet(String url, Map<String, String> headers) throws IOException {
        final int TIMEOUT_MILLIS = 0;// タイムアウトミリ秒:0は無限
        final StringBuffer sb = new StringBuffer("");

        HttpURLConnection httpConn = null;
        BufferedReader br = null;
        InputStream is = null;
        InputStreamReader isr = null;

        try {
            URL urlObj = new URL(url);
            httpConn = (HttpURLConnection) urlObj.openConnection();
            httpConn.setConnectTimeout(TIMEOUT_MILLIS);// 接続にかかる時間
            httpConn.setReadTimeout(TIMEOUT_MILLIS);// データの読み込みにかかる時間
            httpConn.setRequestMethod("GET");// HTTPメソッド
            httpConn.setUseCaches(false);// キャッシュ利用
            httpConn.setDoOutput(false);// リクエストのボディの送信を許可(GETのときはfalse,POSTのときはtrueにする)
            httpConn.setDoInput(true);// レスポンスのボディの受信を許可

            if (headers != null) {
                for (String key : headers.keySet()) {
                    httpConn.setRequestProperty(key, headers.get(key));// HTTPヘッダをセット
                }
            }

            final int responseCode = httpConn.getResponseCode();

            String encoding = httpConn.getContentEncoding();
            if (encoding == null) {
                encoding = "UTF-8";
            }

            if (responseCode == HttpURLConnection.HTTP_OK) {
                is = httpConn.getInputStream();
                isr = new InputStreamReader(is, encoding);
                br = new BufferedReader(isr);
                String line = null;
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
            } else {
                // ステータスがHTTP_OK(200)以外の場合
                throw new IOException("responseCode is " + responseCode);
            }

        } catch (IOException e) {
            throw e;
        } finally {
            // Java1.6 Compliant
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                }
            }
            if (isr != null) {
                try {
                    isr.close();
                } catch (IOException e) {
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                }
            }
            if (httpConn != null) {
                httpConn.disconnect();
            }
        }
        return sb.toString();
    }
}

まとめ

  • JavaでHTTP通信をするやり方も2通り紹介しました

    • OkHttp3を使ったやり方
    • Java標準パッケージであるHttpUrlConnectionを使ったやり方
  • 全ソースコードはこちらにあります

24
32
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
32