I have the following enum declaration:
@Document
@JsonFormat(shape= JsonFormat.Shape.OBJECT)
@JsonAutoDetect()
public enum Compass {
north("Upper Center"),
south("Lower Center"),
east("Left Center"),
west("Right Center"),
ne("Upper Right"),
nw("Upper Left"),
se("Lower Right"),
sw("Lower Left"),
;
@JsonProperty
private String presentableName;
@JsonProperty
private String name;
private Compass() {}
private Compass(String presentableName) {
this.presentableName = presentableName;
}
public String getPresentableName() {
return presentableName;
}
public void setPresentableName(String presentableName) {
this.presentableName = presentableName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@JsonCreator
public static Compass fromObject(@JsonProperty("name") String name, @JsonProperty("presentableName") String presentableName) {
return Compass.sw;
}
}
The input arrives as a json object and most of it is deserialized correctly, but the relevant part is as below, where placement
is a Compass
:
{"placement":{"name":"se","presentableName":"Lower Right"}}
Deserialization doesn't work. I thought a JsonCreator
would work here, but for some reason I'm getting a
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json;charset=UTF-8' not supported
which is actually just a symptom of deserialization failure.
If I change the creator to:
@JsonCreator
public static Compass fromObject(@JsonProperty("name") String name) {
return Compass.sw;
}
It gets even more wierd, because now name equals {
instead of se
(which looks like a bug in the json object, but it's the same object that got deserialized a second ago so it's probably ok)
I'm using jackson 2.2.3
which is the latest right now.
By default, Jackson will use the Enum name to deserialize from JSON. If we want Jackson to case-insensitively deserialize from JSON by the Enum name, we need to customize the ObjectMapper to enable the ACCEPT_CASE_INSENSITIVE_ENUMS feature.
In order to serialize Enum, we take the help of ObjectMapper class. We use the writeValueAsString() method of ObjectMapper class for serializing Enum. If we serialize Enum by using the writeValueAsString() method, it will represent Java Enums as a simple string.
You can serialize the enum by converting the enum to its ordinal() value.
Whilst I still agree with @renatoaraujoc's answer, I've found a (somehow hacky) solution to this problem.
Just create a @JsonCreator
annotated method which receives a Map<String, Object>
. Jackson deserializes the compound object into a Map as passes it to the method:
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum TesterEnum {
FirstValue(1, "One"),
SecondValue(2, "Two");
private int id;
private String dsc;
TesterEnum(int id, String dsc) {
this.id = id;
this.dsc = dsc;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDsc(){
return dsc;
}
public void setDsc(String dsc){
this.dsc = dsc;
}
@JsonCreator
public static TesterEnum fromObject(final Map<String, Object> obj) {
if (obj != null && obj.containsKey("id")) {
Integer id = null;
if (obj.get("id") instanceof Integer) {
id = (Integer)obj.get("id");
} else {
id = Integer.parseInt((String)obj.get("id"));
}
return fromId(id);
}
return null;
}
public static TesterEnum fromId(final Integer id) {
if (id != null) {
for (TesterEnum e : TesterEnum.values()) {
if (id.equals(e.getId())) return e;
}
}
return null;
}
}
P.S.: You don't really need the fromId
method, it can be all put into fromObject
, but I use the first on other parts of the system and like to have this separation.
P.S.²: Jackson normally decode the id
field into an Integer
instance, so it enters the if (obj.get("id") instanceof Integer)
on fromObject
, but I've seen it being cast to String
sometimes, that's why I'm checking.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With