从JSON反序列化java枚举
我们使用Jackson 1.9.1对Java对象的JSON请求-响应字符串进行序列化和反序列化。基本Java类型、集合类型和自定义对象是(反)序列化的,没有问题。然而,我在尝试将JSON字符串反序列化为java枚举时遇到了一个问题。 JSON字符串序列化如下:从JSON反序列化java枚举,java,json,enums,jackson,Java,Json,Enums,Jackson,我们使用Jackson 1.9.1对Java对象的JSON请求-响应字符串进行序列化和反序列化。基本Java类型、集合类型和自定义对象是(反)序列化的,没有问题。然而,我在尝试将JSON字符串反序列化为java枚举时遇到了一个问题。 JSON字符串序列化如下: "wt":{"wt":100.5,"unit":{"LBS":3}} wt的Java类型如下所示: public class Weight { protected double weight; protected Un
"wt":{"wt":100.5,"unit":{"LBS":3}}
wt的Java类型如下所示:
public class Weight {
protected double weight;
protected Unit unit;
}
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;
}
}
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)
我参考了,等等,并提出了重量单位的枚举,如下所示:
public class Weight {
protected double weight;
protected Unit unit;
}
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;
}
}
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时,我都会遇到这样的错误:“未识别的字段”LBS(Class a.b.c.d.Weight),未标记为可忽略”异常stacktrace如下所示:
public class Weight {
protected double weight;
protected Unit unit;
}
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;
}
}
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字符串是否正确?
要正确反序列化枚举,我还应该包括(或注释)哪些内容?我假设在
公共枚举单元
代码块中,您的意思是单元
,而不是权重度量单位
Weight
类只有一个Weight
和一个unit
,因此如果你通过{“wt”:100.5,“unit”:“lbs”}
,它应该可以工作,因为unit
只是一个没有值的单位。因此,反序列化程序无法将{“LBS”:3}
作为单元进行解析。3
的作用是什么
另一个问题是,你的价值是“磅”,而你是通过“磅”。因此,您要么需要标准化,要么需要使用unit.getValue().equalsIgnoreCase(val)
我建议您将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()方法:
您不需要任何注释或自定义反序列化程序。
这是将简单枚举映射到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;
}
}
只是猜测-看起来它在序列化时按顺序对枚举字段进行编号,KG=1,GM=2,等等。如果您使用这些数字作为枚举初始值设定项,即使用KG(1),是否有效;总经理(2);磅(3);OZ(4);在枚举单位的定义中?您的问题对我的问题进行了排序。我在寻找注释@JsonValue
和@JsonCreator
。非常正确;在获取值的getValue/OverridentOstring上添加了@JsonValue
,在匹配EnumName/EnumValue的matchFromString自定义方法上添加了@JsonCreator
!我认为问题中的字符串是它是如何序列化JSON的——因此无法直接控制更改itRaze2Dust:我的错误。是的,我指的是Unit而不是WeightMeasurementUnit。我对JSON的序列化方式几乎没有控制权。但是,在我可以说JSON序列化错误之前,我想确保我没有对枚举做任何错误。谢谢。@Raze2Dust:这就是问题所在。以这种方式序列化JSON的代码对ObjectMapper使用了错误的映射。我刚刚更改了我的单元枚举以覆盖toString,并在末尾用(at)JsonValuevalue对其进行了注释。单元枚举类中没有定义值