Help us understand the problem. What is going on with this article?

JacksonつかってJavaオブジェクトをJSONに変換する際、enum型を数値で出力する

More than 5 years have passed since last update.

JacksonっていうのはJavaオブジェクトをJSON文字列に変換してくれる便利なアレです。
Jackson自体に関してはいろいろ記事があるのでそれを参考にしてください。

enumが文字列として出力されてしまうのダルい

今回の問題点は、以下です。

Javaオブジェクトにenum型が含まれる場合、値が数値ではなくキーの文字列として出力されてしまう

例えば以下。

// enum型を定義
public enum DayOfWeek {
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
}

// オブジェクトのクラスを定義
public class PeriodicTodo implements Serializable {
    private String todo;
    private DayOfWeek day;

    public String getTodo() { return todo; }
    public void setTodo(String todo) { this.todo = todo; }

    public DayOfWeek getDay() { return day; }
    public void setDay(DayOfWeek day) { this.day = day; }
}

あとはこれを使ってJavaオブジェクトをJSONにシリアライズ

// インスタンス生成
PeriodicTodo todo = new PeriodicTodo();
todo.setTodo('do something');
todo.setDay(DayOfWeek.Monday);


// シリアライズ
ObjectMapper mapper = new ObjectMapper();
String serialized = mapper.writeValueAsString(todo);
System.out.println(serialized);

// ホントはMondayを数値で出力したかった!!
// 結果 ==> { "todo":"do something","day":"Monday" }

enumでも独自にシリアライズできるようにする

dayは数値で出力したいっていう場合には独自のシリアライザを作りましょう。

以下のようにenumにJsonSerializableを実装し、Jsonシリアライズ可能にしてやります。

// enum型をシリアライズ可能に
public enum DayOfWeek implements JsonSerializable {
    Sunday,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday;

    @Override
    public void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        jgen.writeNumber(ordinal());
    }

    @Override
    public void serializeWithType(JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer)  throws IOException, JsonProcessingException  {
        jgen.writeNumber(ordinal());
    }
}

あとはさっきと同じことすれば見事数字で出力されます

// インスタンス生成
PeriodicTodo todo = new PeriodicTodo();
todo.setTodo('do something');
todo.setDay(DayOfWeek.Monday);


// シリアライズ
ObjectMapper mapper = new ObjectMapper();
String serialized = mapper.writeValueAsString(todo);
System.out.println(serialized);

// 結果 ==> { "todo":"do something","day":1 }

enumでもimplementsできるなんて地味に知らなかった。

muran001
2014年6月から大手SIerに見切りをつけてWeb系のエンジニアとして活動してます。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away