2015-06-11 75 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);