简体   繁体   中英

Jackson deserialise sub-type sets enum field to null

Update: superfluous code removed

I need to deserialised a JSON object which can be one of many sub-types of a parent class. Which specific sub-type it is is determined by a specific enum field in the object. I've added @JsonTypeInfo and @JsonSubTypes annotations to the parent class and as far as I can tell they're all correct.

However, the enum value isn't exactly the same as the enum's name in the Java class. So, in the enum class I've annotated a static method with @JsonCreator so Jackson knows how to deserialise the value to a proper Java enum.

The issue I have is that once I deserialise the JSON string, the field holding the enum doesn't contain the actual enum value - it's left as null .

Why is the day field left as null and how can I set it as expected during deserialisation?

Code below.

Parent Calendar class

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "day")
// For the sake of correct deserialisation, we need to map from values of type to child model classes explicitly
@JsonSubTypes({ @JsonSubTypes.Type(value = Monday.class, name = "monday"),
   @JsonSubTypes.Type(value = Monday.class, name = "mon"),
   @JsonSubTypes.Type(value = Tuesday.class, name = "tuesday"),
   @JsonSubTypes.Type(value = Tuesday.class, name = "tues")})
public class Calendar {
   protected String calendarName;
   protected DaysOfWeek day;

   @JsonProperty("calendarName")
   public String getCalendarName() {
      return calendarName;
   }

   public void setCalendarName(String calendarName) {
      this.calendarName = calendarName;
   }

   @JsonProperty("day")
   public DaysOfWeek getDay() {
      return day;
   }

   public void setDay(DaysOfWeek day) {
      this.day = day;
   }
}

Child classes Monday and Tuesday Monday

public class Monday extends Calendar {
   private NegativeFeelings object;

   public Monday() {
   }

   public Monday(NegativeFeelings object) {
      this.object = object;
   }

   @JsonProperty("object")
   public NegativeFeelings getObject() {
      return object;
   }

   public void setObject(NegativeFeelings object) {
      this.object = object;
   }
}

Tuesday

public class Tuesday extends Calendar {
   private Meetings object;

   public Tuesday() {
   }

   public Tuesday(Meetings object) {
      this.object = object;
   }

   @JsonProperty("object")
   public Meetings getObject() {
      return object;
   }

   public void setObject(Meetings object) {
      this.object = object;
   }
}

DaysOfWeek enum class

public enum DaysOfWeek {
   MONDAY("monday"),
   MON("mon"),
   TUESDAY("tuesday"),
   TUES("tues");

   private String value;

   DaysOfWeek(String value) {
      this.value = value;
   }

   @Override
   @JsonValue
   public String toString() {
      return String.valueOf(value);
   }

   @JsonCreator
   public static DaysOfWeek fromEventString(@JsonProperty("value") String eventString) {
      return Arrays.stream(DaysOfWeek.values()).filter(e -> e.value.equals(eventString)).findFirst().get();
   }
}

JSON source string

{
  "calendarName":"My Tuesdays",
  "day":"tuesday",
  "object":{
    "meetings":[
      "team",
      "company",
      "client"]
  }
}

Deserialised object (deserialised from above string)

Tuesday {
  object=Meetings {
  meetings=[team, company, client]
},
  calendarName=My Tuesdays,
  day=null //I want this to be "tuesday", not null
}

Found the answer via colleague.

I needed to set the visible property of the @JsonTypeInfo annotation to true :

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "day", visible = true)
// For the sake of correct deserialisation, we need to map from values of type to child model classes explicitly
@JsonSubTypes({ @JsonSubTypes.Type(value = Monday.class, name = "monday"),
   @JsonSubTypes.Type(value = Monday.class, name = "mon"),
   @JsonSubTypes.Type(value = Tuesday.class, name = "tuesday"),
   @JsonSubTypes.Type(value = Tuesday.class, name = "tues")})
public class Calendar {
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM