ton*_*nga 5 java enums json jackson deserialization
我想使用Jackson JSON序列化/反序列化包含枚举对象的类.我的班级是:
class Bar {
@JsonProperty("rateType")
@JsonDeserialize(using = ReturnedRateTypeDeserializer.class)
private ReturnedRateType rateType;
public ReturnedRateType getRateType() {
return rateType;
}
public void setRateType(ReturnedRateType rateType) {
this.rateType = rateType;
}
}
Run Code Online (Sandbox Code Playgroud)
枚举类ReturnedRateType定义为:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我添加了@JsonFormat注释,告诉Jackson将此枚举序列化为POJO,并添加@JsonCreator注释以获取从给定字符串到枚举对象的静态工厂方法.由于Jackson只能序列化但无法从对象表示反序列化为枚举,因此我为枚举添加了以下自定义反序列化器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");
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我测试从JSON字符串到枚举的反序列化时,我得到了错误.JSON字符串是:
{"rateType": {"value": "AA"}}
Run Code Online (Sandbox Code Playgroud)
我的测试代码是:
@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());
}
Run Code Online (Sandbox Code Playgroud)
我希望看到输出应该是AA.但jp.getValueAsString()在我的自定义反序列化器ReturnedRateTypeDeserializer执行期间为null:
ReturnedRateType type = ReturnedRateType.fromValue(jp.getValueAsString()); //jp.getValueAsString() is null here!
Run Code Online (Sandbox Code Playgroud)
因此它返回错误.那么这里有什么问题?
根据杰克逊2.5.X关于JsonFormat注释的文档,这Shape.Object不适用于枚举反序列化:
我让JsonCreator静态方法接受JsonNode并从中读取字符串值.
请注意,这将起作用2.5.X.在早期版本中,您需要编写自定义反序列化器.这是一个例子:
public class JacksonEnumObjectShape {
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
@JsonDeserialize(using = ReturnedRateTypeDeserializer.class)
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 JsonNode jsonNode) {
for (ReturnedRateType type : ReturnedRateType.values()) {
if (type.value.equals(jsonNode.get("value").asText())) {
return type;
}
}
return null;
}
}
// can be avoided since 2.5
public static class ReturnedRateTypeDeserializer extends JsonDeserializer<ReturnedRateType> {
@Override
public ReturnedRateType deserialize(
final JsonParser jp,
final DeserializationContext ctxt) throws IOException {
final JsonNode jsonNode = jp.readValueAsTree();
return ReturnedRateType.fromValue(jsonNode);
}
}
public static void main(String[] args) throws IOException {
final ObjectMapper mapper = new ObjectMapper();
final String json = mapper.writeValueAsString(ReturnedRateType.AA);
System.out.println(json);
System.out.println(mapper.readValue(json, ReturnedRateType.class));
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
{"value":"AA"}
AA
Run Code Online (Sandbox Code Playgroud)