2012-03-09 4 views
1

Я хочу десериализовать некоторые логические значения, которые я получаю в JSON. Проблема в том, что эти значения могут быть нулевыми, истинными, ложными, «истинными», ложными, «Y» или «N».Jackson Deserialize custom boolean json property

Я создал свой собственный булево десериализатор

public class CustomBooleanDeserializer extends JsonDeserializer<Boolean> { 

    final protected Class<?> _valueClass = Boolean.class; 

    @Override 
    public Boolean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, 
      JsonProcessingException { 
     return _parseBooleanPrimitive2(jp, ctxt); 
    } 

    protected final boolean _parseBooleanPrimitive2(JsonParser jp, DeserializationContext ctxt) 
      throws IOException, JsonProcessingException { 
     LogUtils.d("PARSE BOOLEAN"); 
     JsonToken t = jp.getCurrentToken(); 
     if (t == JsonToken.VALUE_TRUE) { 
      return true; 
     } 
     if (t == JsonToken.VALUE_FALSE) { 
      return false; 
     } 
     if (t == JsonToken.VALUE_NULL) { 
      return false; 
     } 
     if (t == JsonToken.VALUE_NUMBER_INT) { 
      return (jp.getIntValue() != 0); 
     } 
     if (t == JsonToken.VALUE_STRING) { 
      String text = jp.getText().trim(); 
      if ("true".equals(text)) { 
       return true; 
      } 
      if ("false".equals(text) || text.length() == 0) { 
       return Boolean.FALSE; 
      } 

      if ("N".equalsIgnoreCase(text) || text.length() == 0) { 
       return Boolean.FALSE; 
      } 

      if ("Y".equalsIgnoreCase(text)) { 
       return Boolean.TRUE; 
      } 
      throw ctxt.weirdStringException(_valueClass, "only \"true\" or \"false\" recognized"); 
     } 
     // Otherwise, no can do: 
     throw ctxt.mappingException(_valueClass); 
    } 

Однако это десериализатор никогда не вызывается, если я зарегистрировать его как это:

Version version = new Version(1, 0, 0, "SNAPSHOT"); 
SimpleModule module = new SimpleModule("MyModuleName", version); 
module = module.addDeserializer(new CustomBooleanDeserializer()); 
objectMapper.registerModule(module); 

Если, с другой стороны, я использую @JsonDeserialize(using = CustomBooleanDeserializer.class) для булевых полей он вызывает вызов и отлично работает. Единственная проблема заключается в том, что если свойство имеет нулевое значение, я получаю это исключение:

org.codehaus.jackson.map.JsonMappingException: Проблема десериализация свойства «show_query_cond» (ожидаемый типа: [простой тип, класс булевых ]; фактический тип: [NULL]), проблема: недействительное значение для поля (через эталонную цепь: com.csf.model.CSTable [ "show_query_cond"])

Таким образом, если логическое свойство имеет нулевое значение, у моего десериализатора нет возможности запустить. Кроме того, я попытался использовать mapper.configure(DeserializationConfig.Feature.FAIL_ON_NULL_FOR_PRIMITIVES, false);, но исключение все равно бросается, если я использую аннотацию @JsonDeserialize.

Кто-нибудь знает, как сделать эту работу?

ответ

7

Что касается регистрации, это, вероятно, связано с Java, имеющей как примитивные boolean, так и обертку объекта Boolean. Поэтому вам нужно зарегистрировать его, используя как java.lang.Boolean, так и Boolean.TYPE - последний является классом заполнителя для примитивного типа.

Нулевая обработка - это другая проблема: метод десериализации не называется для них. Однако существует метод

JsonDeserializer.getNullValue() 

, который следует называть; и для примитивов вам нужно просто вернуть «Boolean.FALSE», так как вы не можете присвоить значение null примитивному значению (нормально возвращать завернутый, он правильно обрабатывается).

2

В пользовательской десериализации, вы можете переопределить метод getNullValue к вашему значению по умолчанию:

до 2,6

@Override 
public Boolean getNullValue() { 
    return Boolean.FALSE; 
} 

2.6+

@Override 
public Boolean getNullValue(DeserializationContext ctxt) { 
    return Boolean.FALSE; 
} 
Смежные вопросы