I want to use Jackson JSON to serialize/deserialize a class containing an enum object. My class is:
class Bar {
@JsonProperty("rateType")
@JsonDeserialize(using = ReturnedRateTypeDeserializer.class)
private ReturnedRateType rateType;
public ReturnedRateType getRateType() {
return rateType;
}
public void setRateType(ReturnedRateType rateType) {
this.rateType = rateType;
}
}
The enum class ReturnedRateType is defined as:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum ReturnedRateType {
AA("AA"),
BB("BB"),
CC("CC");
@JsonProperty("value")
private String value;
ReturnedRateType(String value) {
this.value = value;
}
@JsonCreator
public static ReturnedRateType fromValue(final String value) {
if (value != null) {
for (ReturnedRateType type : ReturnedRateType.values()) {
if (value.equalsIgnoreCase(type.value)) {
return type;
}
}
}
return null;
}
}
As you see, I added @JsonFormat
annotation to tell Jackson to serialize this enum as POJO, and added @JsonCreator
annotation to get a static factory method from given string to enum object. Since Jackson can only serialize but can't deserialize from object representation to enum, I added the following customized deserializer for the enum ReturnedRateType
:
public class ReturnedRateTypeDeserializer extends JsonDeserializer<ReturnedRateType> {
@Override
public ReturnedRateType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ReturnedRateType type = ReturnedRateType.fromValue(jp.getValueAsString());
if(type != null)
return type;
throw new JsonMappingException("invalid value for ReturnedRateType");
}
}
But when I tested deserialization from a JSON string to enum, I got the error. The JSON string is:
{"rateType": {"value": "AA"}}
My test code is:
@Test
public void RateTypeToEnum() {
String json = "{\"rateType\": {\"value\": \"AA\"}}";
System.out.println(json);
ObjectMapper mapper = new ObjectMapper();
Bar bar = null;
try {
bar = mapper.readValue(json, Bar.class);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(bar.getRateType());
}
I expect to see the output should be AA
. But jp.getValueAsString()
in my customized deserializer ReturnedRateTypeDeserializer
is null during the execution:
ReturnedRateType type = ReturnedRateType.fromValue(jp.getValueAsString()); //jp.getValueAsString() is null here!
Thus it returns error. So what is wrong here?
@JsonProperty("value")
from the creator method. Without this, assumption is that incoming JSON data must be a single JSON String. Note that@JsonFormat
does not have effect on custom (de)serializers or creators; it only changes behavior of default (de)serializers. So try adding that annotation in there first. – StaxMan@JsonProperty("value")
from the creator method but it still reports the same error. Actually I've put this annotation in thevalue
field of the enum. The error seems to be related tojp.getValueAsString()
returns null, which should return"AA"
which is the string value of the given enum. – tonga