スポンサーリンク

JsonをHttpURLConnectionでやり取りする方法

スポンサーリンク

Gson

gsonと呼ばれるライブラリを使用します.調べた限り一番一般的です.以下Maven.

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.7</version>
</dependency>

公式のgithubはこちら.

GitHub - google/gson: A Java serialization/deserialization library to convert Java Objects into JSON and back
A Java serialization/deserialization library to convert Java Objects into JSON and back - google/gson

使い方

恐ろしく簡単です.Collection以外のクラスは以下のようにして変換できます.

T obj;                             //Collection以外のObject
Gson gson = new Gson();
String json = gson.toJson(obj);    //object -> json
T obj2 = gson.fromJson(json, obj); //json -> object

Collection<T>を扱う場合

また,Collectionを扱いたい場合は以下のように実施します.これはCollectionがGenericsであり,jsonでは型情報を保存する手法がないので,deserializeするときに明示的に型指定する必要があるためです.(試しにList.classを渡してもdeserializeしてくれません)

Java Google Json (Gson) Serializing Collections – Studytrails
//Tは適当なObject
Type collectionType = new TypeToken<Collection<T>>(){}.getType();
List<T> lists = gson.fromJson(json, collectionType);

Collectionを持ったWrapperクラスを定義して,それを渡したほうが可読性的にもいいと思いますね.

Genericsクラスを扱う

上記で想像がつくかもしれませんが,他のGenericsクラスをdeserializeするときも上記と同様の手法を用います.

Java Google Json (Gson) Serializing Generics – Studytrails
Type type = new TypeToken<GenericClass<String>>(){}.getType();
GenericClass<String> obj = gson.fromJson(json, type);

jsonにnull値を含める

jsonで {“id” : null}と表示してほしい場合には,以下からGsonを作製します.jsonの可読性を高める目的だけで,json -> Objectへのdeserializeは問題なくこのオプションに関係なく可能です.(null値のObjectはnullになる)

GsonBuilder builder = new GsonBuilder();
builder.serializeNulls();
Gson gson = builder.create();

jsonでprivate フィールドを除く

Interface部だけ取り出したい場合は以下のようにしてPrivateなどのフィールドは除くことができるようです.

GsonBuilder builder = new GsonBuilder();  
builder.excludeFieldsWithModifiers(Modifier.PRIVATE); 

特定のクラスにだけ特別なSerialize/Deserializeを行う

確かにこれ使いたいときありますよね.備忘録としてリンクだけ貼っておきます.

Java Google Json (Gson) Type Adapter – Studytrails

HttpURLConnectionによる通信

Client

JsonTransferというInnerClassをJsonで送信します.Android用のHttpURLConnectionになります.

private void sendJson(){    
        List<JsonTransfer> items = new ArrayList<>();
        items.add(new JsonTransfer("json1", 343));
        items.add(new JsonTransfer("json2", 34777));
        items.add(new JsonTransfer(null, 6464));
        GsonBuilder builder = new GsonBuilder();
        builder.serializeNulls();
        Gson gson = builder.create();
        String json = gson.toJson(items);
        Log.e("test", json);

        HttpURLConnection con = null;
        //post
        try{
            URL url = new URL("https://localhost:8080/application/anywhere");
            con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("POST"); //POSTを使用
            con.setDoOutput(true);     //Requestにボディを持たせます.
            con.setDoInput(true);     //Defaultでtrueなのでなくてもよい
            con.setRequestProperty("Content-Type", "application/json; charset=utf-8"); //jsonを指定する
            try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(con.getOutputStream(), StandardCharsets.UTF_8))){
                writer.write(json);
            }

            if(con.getResponseCode() == HttpURLConnection.HTTP_OK){
                try(BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8))){
                    StringBuilder builder1 = new StringBuilder();
                    String line = null;
                    while((line = reader.readLine()) != null){
                        builder1.append(line);
                    }
                    Log.e("test", "recv:" + builder1.toString());
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            if(con != null){
                con.disconnect();
            }
        }
}

private static class JsonTransfer{
    private String name;
    private int id;

    public JsonTransfer(String name, int id) {
        this.name = name;
        this.id = id;
    }
}

Server

HttpServletで受け取る場合を記載します.なお,InnerClassにJsonTransferを定義していますが,本来はServerかClientがどちらかに依存してそれを参照するようにすべきで,両方に記載すべきではありません.逆に言えば,Gsonはフィールド名が一致していたらそのクラスで読み込んでくれるということですね.

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        BufferedReader reader = new BufferedReader(req.getReader());
        String json = reader.readLine();
        System.out.println("recv json:" + json);
        Gson gson = new Gson();
        Type collectionType = new TypeToken<Collection<JsonTransfer>>(){}.getType();
        List<JsonTransfer> recordItems = gson.fromJson(json, collectionType);
        for(JsonTransfer item : recordItems){
            System.out.println(item.name + "," + item.id);
        }
    }

 private static class JsonTransfer{
    private String name;
    private int id;

    public JsonTransfer(String name, int id) {
        this.name = name;
        this.id = id;
    }
} 
タイトルとURLをコピーしました