Em fasterxml, depois de JSON desserialização, se enum (com JsonFormat.Shape.OBJECT) é a primeira propriedade em classe, outros campos são nulos.
Por enum deve ser passada declarou propriedade na classe para desserializar outros campos corretamente?
Talvez isso poderia ser um bug no fasterxml?
Exemplo classe 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;
}
}
Exemplo enum 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;
}
}
Exemplo principal classe de teste 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));
}
}
Saída mostrando campo é null
após a desserialização:
serialized - {
"option" : {
"option" : "FIRST"
},
"element" : "elem"
}
deserialized - {
"option" : {
"option" : "FIRST"
},
"element" : null
}
Saída após a fixação fim (linhas descomentei em MyClass
):
serialized - {
"element" : "elem",
"option" : {
"option" : "FIRST"
}
}
deserialized - {
"element" : "elem",
"option" : {
"option" : "FIRST"
}
}
Eu não poderia dizer se é um bug, você pode depurar e passo através do código para entender como Jackson "falhar" neste cenário. O uso de FAIL_ON_UNKNOWN_PROPERTIES
peles do problema, que está usando String
como o tipo de parâmetro do seu forValue
método de fábrica. Em suma, Jackson fica "preso" em atravessar as fichas do conteúdo JSON.
Para corrigi-lo corretamente, ou seja. Não confie em ordem, você tem um par de opções. Em primeiro lugar, livrar-se da JsonFormat.Shape.OBJECT
forma para a serialização do tipo enum e seu correspondente @JsonCreator
. O padrão de serialização / desserialização para um enum é usar seu nome de qualquer maneira.
Em segundo lugar, se você realmente quiser manter a forma do objeto, você precisa mudar o seu @JsonCreator
método para receber um ObjectNode
, já que é o que o JSON contém, não um String
. De lá, você pode executar a desserialização-se (supondo que você tem mais constantes enum)
@JsonCreator
public static MyEnum forValue(ObjectNode object) {
return MyEnum.valueOf(object.get("option").asText());
}