Pocket

こんにちは。itouです。
今回は、JSONのレスポンスをenum列挙型にマッピングする方法です。

Jackson JSON Processorで、下記のようにJSONのレスポンスをResponseJsonクラスにマッピングしてみます。

・JSONのレスポンスbody内容

{"stringParameter":"HOGE","enumParameter":"1"}

・JSONのレスポンスbodyをResponseJsonクラスにマッピング

CloseableHttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
byte[] body = EntityUtils.toByteArray(entity);
ResponseJson responseJson = OBJECT_MAPPER.readValue(body, ResponseJson.class);

・ResponseJsonクラス

@JsonIgnoreProperties(ignoreUnknown = true)
public class ResponseJson implements Serializable {

    private static final long serialVersionUID = 3030664960834078285L;

    private String stringParameter;

    private EnumParameter enumParameter;
    
    
    public String getStringParameter() {
        return stringParameter;
    }

    public void setStringParameter(String stringParameter) {
        this.stringParameter = stringParameter;
    }

    public EnumParameter getEnumParameter() {
        return enumParameter;
    }

    public void setEnumParameter(EnumParameter enumParameter) {
        this.enumParameter = enumParameter;
    }

・enum列挙型

public enum EnumParameter {
    TOKYO("東京", "1"),
    OSAKA("大阪", "2");

    private String name;

    private String code;

    CouponRewardCode(String name, String code) {
        this.name = name;
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public String getCode() {
        return code;
    }

    public static EnumParameter get(String code) {
        for (EnumParameter enumCode : EnumParameter.values()) {
            if (StringUtils.equals(enumCode.getCode(), code)) {
                return enumCode;
            }
        }
        return null;
    }
}

意図としてはレスポンスの「"enumParameter":"1"」がResponseJsonのenumParameterに「TOKYO("東京", "1")」と設定されてほしいのですが

Caused by: org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.globalrelay.gas.appsjson.authportal.Event from String value 'enumParameter': value not one of declared Enum instance names

というエラーが発生します。

その場合、下記の通りDeserializerを定義し、enumクラスに「@JsonDeserialize(using = EnumParameterDeserializer.class)」アノテーションを設定することで、
code("1")が来たら、enumValue(TOKYO("東京", "1"))が設定されるようにできます。

public class EnumParameterDeserializer extends JsonDeserializer<Object> {
   @Override
    public EnumParameter deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        final String jsonValue = jp.getText();
        for (final EnumParameter enumValue : EnumParameter.values()) {
            if (enumValue.getCode().equals(jsonValue)) {
                return enumValue;
            }
        }
        return null;
    }
}

逆にSerializerも可能です。

public class EnumParameterSerializer extends JsonSerializer<CouponRewardCode> {
    @Override
    public void serialize(EnumParameter value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        jgen.writeString(value.getCode());
    }
}