2015-09-11 5 views
0

У меня есть тип, называемый OptionalField<T>, который может быть либо пустым(), defined(value) (как обычный факультативный), либо nullValue(default) (представляет собой значение по умолчанию в JSON, которое может быть чем-то вроде "n/a" или такой).Jackson deserialize generic class, custom optional

Моя проблема с Джексоном, потому что мне нужно создать собственный сериализатор и десериализатор, способный идентифицировать общий тип и найти соответствующий сериализатор по умолчанию, десериализатор. У меня не было особых проблем, создавая сериализатор с контекстную интерфейсом, поскольку он предоставляет свойство и Serializer provider

public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { 
    ... 
    JsonSerializer<Object> serialiser = prov.findValueSerializer(property.getType().containedType(0).getRawClass(), property); 
    ... 
} 

Но десериализатор что-то еще, я не могу найти способ, чтобы определить тип и и найти десериализации по умолчанию. Вы знаете, как я могу это сделать? Я читал некоторые вещи о BeanDeserializers, но я не думаю, что он отвечает на мою проблему.

Update

Я прошел через библиотеку https://github.com/FasterXML/jackson-datatype-jdk8, чтобы понять, как они это делают, и это, кажется, очень низкий уровень манипуляции (типы и SCALA). Неужели нет другого способа сделать это? Еще один способ использовать Джексона? Это действительно похоже на общий прецедент для меня (общие классы, которые я имею в виду)?

ответ

1

Использование параметров типа в сериализаторе/десериализаторе не все , что общий, по моему опыту. Это сложнее, чем могло бы быть, частично из-за того, как параметры типа были исправлены на Java с версии 1.5. Это затрудняет право на что-либо, кроме простых случаев. Даже пример сериализатора, который вы даете, выглядит так, как будто он работает только для непараметризированных классов, так как он находит сериализатор, основанный только на сыром T (что, если у вас есть OptionalField<Set<SomeObject>>?)

Дополнения типа ddd-типа jdk8 или guava начать. Да, они могут казаться сложными, но эта сложность (по большей части) существует по какой-то причине. Я адаптировал их для поддержки сериализации/десериализации некоторого другого типа Optional типа (fj.Option), так что это, безусловно, возможно.

При реализации Deserializers, метод findBeanDeserializer вызывается с контекстом, где имущество было здесь так установленным размером, вы должны иметь полный вид со всеми его параметрами:

@Override 
    public JsonDeserializer<?> findBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc) 
      throws JsonMappingException { 
     Class<?> raw = type.getRawClass(); 
     if (raw == Option.class) { 
      JavaType[] types = config.getTypeFactory().findTypeParameters(type, Option.class); 
      JavaType refType = (types == null) ? TypeFactory.unknownType() : types[0]; 
      JsonDeserializer<?> valueDeser = type.getValueHandler(); 
      TypeDeserializer typeDeser = type.getTypeHandler(); 
      // [Issue#42]: Polymorphic types need type deserializer                  
      if (typeDeser == null) { 
       typeDeser = config.findTypeDeserializer(refType); 
      } 
      return new FJOptionDeserializer(type, refType, typeDeser, valueDeser); 
     } 
     return super.findBeanDeserializer(type, config, beanDesc); 
    } 
} 

Здесь refType является тип параметр Option, поэтому мы передаем его конструктору десериализатора, то есть каждое вхождение Option в классах, проанализированных Jackson, получит собственный экземпляр десериализатора, настроенный с параметрами типа OptionalField.

По большому счету, я скопировал реализацию Optional, и это сработало довольно легко. Реализация OptionalDeserializer и др. Не самая ясная (поскольку она объединяет два случая в одном классе, imho смущает).