読者です 読者をやめる 読者になる 読者になる

JSONデータ→列挙型は、Google GSONが便利

Google gson を使用してJSONデータをJavaオブジェクトに変換する場合、列挙型への変換をする時としない場合の差異、、

以下のような JSONデータがあるとする。
 [
     { "time": "2015-01-11 10:27:14", "status": 200 } ,
     { "time": "2015-01-11 11:02:48", "status": 404 } ,
     { "time": "2015-01-11 12:18:21", "status": 200 } ,
     { "time": "2015-01-11 12:37:03", "status": 500 }
 ]

リストとして変換されるオブジェクト ResultPage クラスの定義は以下のとおり、
import java.util.Date;
import com.google.gson.annotations.SerializedName;
/**
 * ResultPage.java
 */

public class ResultPage {
   public Date time;
   @SerializedName("status")
   public Integer httpstatus;
}

このように、status は、列挙型にせずに単純に Integer 型にするだけなら、
@SerializedName を付与して
以下のように処理すれば、良い。
SimpleDateFormat sformat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
InputStreamReader inputReader = new InputStreamReader(new FileInputStream("status.json"), "UTF-8");

Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm:ss").create();

Type collectionType
 = new TypeToken<Collection<ResultPage>>(){}.getType();

List<ResultPage> list = gson.fromJson(new JsonReader(inputReader), collectionType);
------------------------
Type collectionType は、java.lang.reflect.Type で、
com.google.gson.reflect.TypeToken から作りだす。

リストとして解析させるためである。

このサンプルデータで、status を列挙型で解釈させる場合、
次のように enum を用意して、
public enum Httpstatus {
   OK            (200) ,
   NOT_FOUND     (404) ,
   SERVER_ERROR  (500) ;
   private int code;
   private Httpstatus(int code){
      this.code = code;
   }
   public int getCode(){
      return code;
   }
   public static final Httpstatus fromCode(int code){
      for(Httpstatus h:Httpstatus.values()){
         if (h.getCode()==code) return h;
      }
      return null;
   }

}

解析結果として変換先のクラス ResultPage は、以下のようにする。
public class ResultPage {
   public Date time;
   @SerializedName("status")
   public Httpstatus httpstatus;
}

JsonDeserializer という専用デシリアライズ処理で列挙型に解釈させるようにするのだが、
それは、GsonBuilder 生成時に約束する。
つまり、以下のようになる。

Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss")
.registerTypeAdapter(Httpstatus.class, new JsonDeserializer<Httpstatus>(){
   @Override
   public Httpstatus deserialize
(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
      return Httpstatus.fromCode(jsonElement.getAsInt());
   }
}).create();

Type collectionType = new TypeToken<Collection<ResultPage>>(){}.getType();
List<ResultPage> list = gson.fromJson(new JsonReader(inputReader), collectionType);