2015-06-11 108 views
3

我有問題反序列化具有多個名稱的值的枚舉。這裏有一個例子:信息是,裏面有多個名稱枚舉的Java類:傑克遜反序列化具有多個名稱的枚舉

public class Info { 
    //... 
    private ContainerFormat format; 
} 

// ContainerFormat.java: 

public enum ContainerFormat { 
    // .... 
    MP4("mp4", "mpeg4"), 
    UNKNOWN("null"); 

    private String name; 
    private List<String> others; 

    ContainerFormat(String name) { 
     this.name = name; 
    } 

    /** The service does not always return the same String for output formats. 
    * This 'other' string fixes the deserialization issues caused by that. 
    */ 
    ContainerFormat(String name, String... others) { 
     this.name = name; 
     this.others = new ArrayList<String>(); 
     for (String other : others) { 
      this.others.add(other); 
     } 
    } 

    @JsonValue 
    @Override 
    public String toString() { 
     return name; 
    } 

    public List<String> otherNames() { 
     return others; 
    } 

    @JsonCreator 
    public static ContainerFormat fromValue(String other) throws JsonMappingException { 
     for (ContainerFormat format : ContainerFormat.values()) { 
      if (format.toString().equalsIgnoreCase(other)) { 
       return format; 
      } 
      if (format.otherNames() != null && format.otherNames().contains(other)) { 
       return format; 
      } 
     } 
     return UNKNOWN; 
    } 
} 

問題是,當我反序列化的東西,包含「MPEG4」,而不是MP4的我得到這個錯誤:

com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of com.foo.ContainerFormat from String value 'mpeg4': value not one of declared Enum instance names 
at [Source: N/A; line: -1, column: -1] (through reference chain: com.foo.Info["format"]) 
    at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:55) 
    at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:650) 
    at com.fasterxml.jackson.databind.deser.std.EnumDeserializer.deserialize(EnumDeserializer.java:85) 
    at com.fasterxml.jackson.databind.deser.std.EnumDeserializer.deserialize(EnumDeserializer.java:20) 
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:375) 
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:308) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121) 
    at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:2769) 
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1478) 
    at com.fasterxml.jackson.databind.ObjectMapper.treeToValue(ObjectMapper.java:1811) 

任何關於如何解決這個問題的指針?

TIA

回答

3

我發現基於一個很好的解決方案弗洛林的回答是:

與傑克遜正確的配置2.7.0-RC2(以及可能還有之前)

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()方法:

public enum EXAMPLE_TYPE { 
START("start"), 
MORE("more"); 

    // the value which is used for matching 
    // the json node value with this enum 
    private final String value; 

    SectionType(final String type) { 
     value = type; 
    } 

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

你不需要任何註釋或自定義解串器。

0

擺脫String nameList<String> other,而是隻有一個領域 - List<String> names@JsonValue

public enum ContainerFormat { 
// .... 
MP4("mp4", "mpeg4"), 
UNKNOWN("null"); 

private List<String> names; 

ContainerFormat(List<String> names) { 
    this.names = new ArrayList<String>(names); 
} 

@JsonValue 
public List<String> getNames() 
{ 
    return this.names; 
} 

@JsonCreator 
public static ContainerFormat getContainerFromValue(String value) throws JsonMappingException { 
    for (ContainerFormat format : ContainerFormat.values()) { 
     if(format.getValues().contains(value)) 
      return format; 
    } 
    return UNKNOWN; 
} 

序列化的單個吸附劑或者,如果你選擇要保留現有的代碼,您可以嘗試註釋otherValues()@JsonValue

+0

我的值只有一個名稱:'M4A(「m4a」)' 這些不適用於這個建議的解決方案。 –

+0

這也會造成序列化枚舉的問題 - 我只想寫出一個名字,而不是整個列表。 –

0

嗯,我找到了一個解決辦法:其中一個標誌做正確的事情,讓我可以讀取MPEG4回:

mapper.configure(org.codehaus.jackson.map.SerializationConfig.Feature.WRITE_NULL_PROPERTIES, false); 
    mapper.configure(org.codehaus.jackson.map.SerializationConfig.Feature.WRITE_ENUMS_USING_TO_STRING, true); 
    mapper.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.READ_ENUMS_USING_TO_STRING, true); 
    mapper.setPropertyNamingStrategy(org.codehaus.jackson.map.PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); 
    mapper.setSerializationInclusion(org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion.NON_EMPTY); 
    mapper.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);