我们使用Jackson 1.9.1对JSON请求响应字符串进行序列化和反序列化。原始Java类型,集合类型和自定义对象(序列化)没有问题。但是,我在尝试将JSON字符串反序列化为java枚举时遇到问题。 JSON字符串是这样序列化的:
"wt":{"wt":100.5,"unit":{"LBS":3}}
wt的Java类型是这样的:
public class Weight {
protected double weight;
protected Unit unit;
}
我在SO上提到了this,this和this,并提出了重量单位的枚举:
public enum Unit {
KG("kg"),
GM("gm"),
LBS("lbs"),
OZ("oz");
private String value;
private WeightMeasurementUnit(String value) { this.value = value; }
@JsonValue
public String getValue() { return this.value; }
@JsonCreator
public static Unit create(String val) {
Unit[] units = Unit.values();
for (Unit unit : units) {
if (unit.getValue().equals(val)) {
return unit;
}
}
return LBS;
}
}
问题是,当我尝试反序列化上面提到的JSON时,我得到这样的错误:“无法识别的字段”LBS“(类a.b.c.d.Weight),未标记为可忽略”异常堆栈跟踪是这样的:
Caused by: org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "LBS" (Class a.b.c.d.Weight), not marked as ignorable
at [Source: java.io.ByteArrayInputStream@20172017; line: 1, column: 464] (through reference chain: a.b.c.d.MyRequest["blah"]->a.b.c.d.AnotherType["wt"]->a.b.c.d.Weight["LBS"])
at org.codehaus.jackson.map.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:53)
at org.codehaus.jackson.map.deser.StdDeserializationContext.unknownFieldException(StdDeserializationContext.java:267)
at org.codehaus.jackson.map.deser.std.StdDeserializer.reportUnknownProperty(StdDeserializer.java:673)
at org.codehaus.jackson.map.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:659)
at org.codehaus.jackson.map.deser.BeanDeserializer.handleUnknownProperty(BeanDeserializer.java:1365)
...
我的问题是: 枚举的序列化JSON字符串是否正确? 我还应该包括(或注释)枚举是否正确反序列化?
答案 0 :(得分:6)
我假设在public enum Unit
代码块中,您的意思是Unit
而不是WeightMeasurementUnit
。
Weight
课程只有weight
和unit
,所以如果你通过{"wt":100.5,"unit":"lbs"}
,它应该有用,因为unit
只是一个没有价值的单位。因此,解串器无法将{"LBS":3}
解析为Unit
。什么是3
?
另一个问题是你的价值是“lbs”,而你传递的是“LBS”。因此,您需要标准化,或者需要使用unit.getValue().equalsIgnoreCase(val)
答案 1 :(得分:2)
我建议你将你的jackson版本更新到2.7.0-rc2(也可能在之前),然后按如下方式配置ObjectMapper:
private ObjectMapper createObjectMapper() {
final ObjectMapper mapper = new ObjectMapper();
// enable toString method of enums to return the value to be mapped
mapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
mapper.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
return mapper;
}
在你的枚举中你只需要覆盖toString()方法:
public enum Unit {
KG,
GM,
LBS,
OZ;
// UPDATE: implicitly already the default so override not needed in this case
@Override
public String toString() {
return name();
}
}
您不需要任何注释或自定义反序列化器。 这将是将简单的枚举映射到json的方法,反之亦然。
如果您的枚举应该从特殊字符串映射,您必须添加一个值字段和一个构造函数,该构造函数指定该字段并返回toString方法中的值。
public enum Unit {
KG("kilogram"),
GM("gram"),
LBS("blah"),
OZ("anything");
Unit(final String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
}