如何处理将空字符串反序列化为Enum?

如何处理将空字符串反序列化为Enum?

问题描述:

我想从Ext JS 4提交表单到使用JSON的Spring 3控制器。我使用的是Jackson 1.9.8的序列化/反序列化,使用Spring内置的Jackson JSON支持。如何处理将空字符串反序列化为Enum?

我有一个状态字段,最初为空记录在一个新记录的域对象。当提交表单时它会生成以下JSON(缩小到几个字段)

{"id":0,"name":"someName","status":""} 

提交以下是在服务器日志中看到后

"nested exception is org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.blah.domain.StatusEnum from String value '': value not one of the declared Enum instance names" 

所以看来杰克逊期待有效的枚举值或根本没有值,包括空字符串。我该如何解决这个问题,无论是在Ext JS,Jackson还是Spring?

我试图创建自己的ObjectMapper如

public class MyObjectMapper extends Object Mapper { 
    public MyObjectMapper() { 
     configure(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); 
    } 
} 

,并发送此作为一个属性MappingJacksonMappingView但这并没有工作。我也尝试将它发送到MappingJacksonHttpMessageConverter,但没有奏效。侧面的问题:我应该在我自己的ObjectMapper中发送哪一个?

对此提出建议?

结束了在EXT JS模型中添加默认值,所以总是有一个值。希望我不必这样做,但这不是什么大问题。

我不熟悉Spring,但为了以防万一,可能更容易来处理在客户端:

Ext.define('My.form.Field', { 
    extend: 'Ext.form.field.Text', 

    getSubmitValue: function() { 
     var me = this, 
      value; 

     value = me.getRawValue(); 

     if (value === '') { 
      return ...; 
     } 
    } 
}); 

您也可以通过禁止其allowBlank属性设置为false提交空字段。

我有同样的问题。我正在阅读带有一些空字符串的JSON流。我无法控制JSON流,因为它来自外部服务。我总是收到相同的错误信息。我试过这里:

mapper.getDeserializationConfig().with(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); 

但没有任何影响。看起来像一个Bug。

+1

我在JIRA开罚单为: http://jira.codehaus.org/browse/JACKSON-873?focusedCommentId=311657 – 2012-10-17 08:44:32

你可以做的另一件事是为你的特定枚举创建一个专用的反序列化器(扩展为org.codehaus.jackson.map.JsonDeserializer),它具有不匹配的事物的默认值。我所做的就是为枚举创建一个抽象反序列化器,它接受它反序列化的类,并在遇到问题时加速这个过程。

public abstract class EnumDeserializer<T extends Enum<T>> extends JsonDeserializer<T> { 
    private Class<T> enumClass; 

    public EnumDeserializer(final Class<T> iEnumClass) { 
     super(); 
     enumClass = iEnumClass; 
    } 

    @Override 
    public T deserialize(final JsonParser jp, 
         final DeserializationContext ctxt) throws IOException, JsonProcessingException { 
     final String value = jp.getText(); 
     for (final T enumValue : enumClass.getEnumConstants()) { 
      if (enumValue.name().equals(value)) { 
       return enumValue; 
      } 
     } 
     return null; 
    } 
} 

这就是泛型类,基本上只需要一个枚举类,遍历枚举值,并检查下一个标记以匹配任何名称。如果他们这样做,则返回它,否则返回null;

然后,如果你有一个枚举MyEnum你会做的EnumDeserializer这样的一个子类:

public class MyEnumDeserializer extends EnumDeserializer<MyEnum> { 
    public MyEnumDeserializer() { 
     super(MyEnum.class); 
    } 
} 

那么无论你声明MyEnum

@JsonDeserialize(using = MyEnumDeserializer.class) 
public enum MyEnum { 
    ... 
}