在fasterxml中,反序列化后json,如果enum在class中第一个属性,其他字段为null
In fasterxml, after deserialization json, if enum is first property in class, other fields are null
在fasterxml中,在反序列化后json,如果枚举(带JsonFormat.Shape.OBJECT)在class中第一个属性,其他字段为空。
为什么要在 class 中最后声明枚举 属性 才能正确反序列化其他字段?
也许这可能是 fasterxml 中的错误?
示例 class MyClass
:
public class MyClass {
// >>>
// >>> element field is null after deserialization
// >>>
private MyEnum option; // first
private String element; // --> null
// >>>
// >>> correctly deserialized if enum is last in order
// >>>
// private String element; // --> "elem"
// private MyEnum option; // last
public MyEnum getOption() {
return option;
}
public void setOption(MyEnum option) {
this.option = option;
}
public String getElement() {
return element;
}
public void setElement(String element) {
this.element = element;
}
}
枚举示例 MyEnum
:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum MyEnum {
FIRST;
@JsonProperty
public String getOption() {
return name();
}
@JsonCreator
public static MyEnum forValue(String option) {
return FIRST;
}
}
示例主要测试 class Main
:
public class Main {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MyClass myClass = new MyClass();
myClass.setElement("elem");
myClass.setOption(MyEnum.FIRST);
String serialized = mapper.writer().withDefaultPrettyPrinter().writeValueAsString(myClass);
System.out.println(String.format("serialized - %s", serialized));
MyClass deserialized = mapper.readValue(serialized, MyClass.class);
String deserializedResult = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(deserialized);
System.out.println(String.format("deserialized - %s", deserializedResult));
}
}
反序列化后输出显示字段为null
:
serialized - {
"option" : {
"option" : "FIRST"
},
"element" : "elem"
}
deserialized - {
"option" : {
"option" : "FIRST"
},
"element" : null
}
固定顺序后的输出(MyClass
中未注释的行):
serialized - {
"element" : "elem",
"option" : {
"option" : "FIRST"
}
}
deserialized - {
"element" : "elem",
"option" : {
"option" : "FIRST"
}
}
我无法告诉您这是否是错误,您可以调试并单步执行代码以了解 Jackson "fails" 在这种情况下的表现。您对 FAIL_ON_UNKNOWN_PROPERTIES
的使用隐藏了问题,即使用 String
作为 forValue
工厂方法的参数类型。简而言之,Jackson 在遍历 JSON 内容的标记中得到 "stuck"。
正确修复它,即。不依赖订单,你有几个选择。首先,去掉用于序列化枚举类型的 JsonFormat.Shape.OBJECT
形状及其对应的 @JsonCreator
。枚举的默认值 serialization/deserialization 无论如何都使用它的名称。
其次,如果您真的想保留 OBJECT 形状,则需要更改 @JsonCreator
方法以接收 ObjectNode
,因为那是 JSON 包含的内容,不是 String
。从那里,您可以自己执行反序列化(假设您有更多枚举常量)
@JsonCreator
public static MyEnum forValue(ObjectNode object) {
return MyEnum.valueOf(object.get("option").asText());
}
在fasterxml中,在反序列化后json,如果枚举(带JsonFormat.Shape.OBJECT)在class中第一个属性,其他字段为空。
为什么要在 class 中最后声明枚举 属性 才能正确反序列化其他字段?
也许这可能是 fasterxml 中的错误?
示例 class MyClass
:
public class MyClass {
// >>>
// >>> element field is null after deserialization
// >>>
private MyEnum option; // first
private String element; // --> null
// >>>
// >>> correctly deserialized if enum is last in order
// >>>
// private String element; // --> "elem"
// private MyEnum option; // last
public MyEnum getOption() {
return option;
}
public void setOption(MyEnum option) {
this.option = option;
}
public String getElement() {
return element;
}
public void setElement(String element) {
this.element = element;
}
}
枚举示例 MyEnum
:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum MyEnum {
FIRST;
@JsonProperty
public String getOption() {
return name();
}
@JsonCreator
public static MyEnum forValue(String option) {
return FIRST;
}
}
示例主要测试 class Main
:
public class Main {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MyClass myClass = new MyClass();
myClass.setElement("elem");
myClass.setOption(MyEnum.FIRST);
String serialized = mapper.writer().withDefaultPrettyPrinter().writeValueAsString(myClass);
System.out.println(String.format("serialized - %s", serialized));
MyClass deserialized = mapper.readValue(serialized, MyClass.class);
String deserializedResult = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(deserialized);
System.out.println(String.format("deserialized - %s", deserializedResult));
}
}
反序列化后输出显示字段为null
:
serialized - {
"option" : {
"option" : "FIRST"
},
"element" : "elem"
}
deserialized - {
"option" : {
"option" : "FIRST"
},
"element" : null
}
固定顺序后的输出(MyClass
中未注释的行):
serialized - {
"element" : "elem",
"option" : {
"option" : "FIRST"
}
}
deserialized - {
"element" : "elem",
"option" : {
"option" : "FIRST"
}
}
我无法告诉您这是否是错误,您可以调试并单步执行代码以了解 Jackson "fails" 在这种情况下的表现。您对 FAIL_ON_UNKNOWN_PROPERTIES
的使用隐藏了问题,即使用 String
作为 forValue
工厂方法的参数类型。简而言之,Jackson 在遍历 JSON 内容的标记中得到 "stuck"。
正确修复它,即。不依赖订单,你有几个选择。首先,去掉用于序列化枚举类型的 JsonFormat.Shape.OBJECT
形状及其对应的 @JsonCreator
。枚举的默认值 serialization/deserialization 无论如何都使用它的名称。
其次,如果您真的想保留 OBJECT 形状,则需要更改 @JsonCreator
方法以接收 ObjectNode
,因为那是 JSON 包含的内容,不是 String
。从那里,您可以自己执行反序列化(假设您有更多枚举常量)
@JsonCreator
public static MyEnum forValue(ObjectNode object) {
return MyEnum.valueOf(object.get("option").asText());
}