Джексон андроид NPE при использовании MixIn - PullRequest
1 голос
/ 19 марта 2019

Мой сервер API использует полиморфные объекты разных типов. Например, у меня есть JSON:

{
  "eventType": "FirstType",
  "eventData": "some-useful-object"
}

и класс kotlin для него:

sealed class NotificationEvent {

  data class SomeUsefulEvent(val eventData: String): NotificationEvent()

}

и класс смешивания:

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "eventType"
)
@JsonSubTypes(
    JsonSubTypes.Type(
        value = NotificationEvent.SomeUsefulEvent::class,
        name = "FirstType"
    )
)
abstract class NotificationEventMixIn

когда я звоню со стороны клиента

jsonMapper.readValue<NotificationEvent>(event.data)

приложение вылетает с NPE:

java.lang.NullPointerException: попытка вызвать метод интерфейса 'java.lang.Object java.util.Map.get (java.lang.Object)' на нуле ссылка на объект в com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector._addFieldMixIns (AnnotatedFieldCollector.java:110) в com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector._findFields (AnnotatedFieldCollector.java:87) в com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector.collect (AnnotatedFieldCollector.java:41) в com.fasterxml.jackson.databind.introspect.AnnotatedFieldCollector.collectFields (AnnotatedFieldCollector.java:36) в com.fasterxml.jackson.databind.introspect.AnnotatedClass._fields (AnnotatedClass.java:349) в com.fasterxml.jackson.databind.introspect.AnnotatedClass.fields (AnnotatedClass.java:321) в com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector._addFields (POJOPropertiesCollector.java:379) в com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.collectAll (POJOPropertiesCollector.java:308) в com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getPropertyMap (POJOPropertiesCollector.java:287) в com.fasterxml.jackson.databind.introspect.POJOPropertiesCollector.getProperties (POJOPropertiesCollector.java:170) в com.fasterxml.jackson.databind.introspect.BasicBeanDescription._properties (BasicBeanDescription.java:164) в com.fasterxml.jackson.databind.introspect.BasicBeanDescription.findProperties (BasicBeanDescription.java:239) в com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._findCreatorsFromProperties (BasicDeserializerFactory.java:346) в com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator (BasicDeserializerFactory.java:330) в com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator (BasicDeserializerFactory.java:255) в com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer (BeanDeserializerFactory.java:214) в com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer (BeanDeserializerFactory.java:137) в com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2 (DeserializerCache.java:411) в com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer (DeserializerCache.java:349) в com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2 (DeserializerCache.java:264) в com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer (DeserializerCache.java:244) в com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer (DeserializerCache.java:142) в com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer (DeserializationContext.java:477) в com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer (ObjectMapper.java:4178) в com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose (ObjectMapper.java:3997) в com.fasterxml.jackson.databind.ObjectMapper.readValue (ObjectMapper.java:3011)

как я могу избежать этого сбоя?

1 Ответ

0 голосов
/ 20 марта 2019

после некоторого времени, потраченного на исследования, я обнаружил, что в AnnotatedFieldCollector#_findFields есть блок for, который вызывает JavaType.getRawClass().getDeclaredFields(), и если он возвращает пустой массив, весь блок for пропускается, map _fields не инициализируется и остается null при вызове _addFieldMixIns.

Это происходит потому, что свойства не являются полями в kotlin, а родительский класс не имеет их.

Эту проблему можно обойти, добавив аннотированное свойство @JvmField в класс NotificationEvent следующим образом:

sealed class NotificationEvent {

  @Suppress("unused")
  @JvmField val stub: Int = 0

  data class SomeUsefulEvent(val eventData: String): NotificationEvent()

}

и все отлично работает!

Я надеюсь, что этот вопрос кому-нибудь поможет, и я призываю команду Джексона исправить эту ошибку

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...