使用MixIn时,杰克逊android NPE

时间:2019-03-19 10:02:17

标签: java android kotlin jackson

我的服务器api使用不同类型的多态对象。例如,我有一个json:

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

和kotlin类:

sealed class NotificationEvent {

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

}

和mixin类:

@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)'在null上   对象参考           在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 :(得分:0)

经过一段时间的研究,我发现在AnnotatedFieldCollector#_findFields中有一个for块调用JavaType.getRawClass().getDeclaredFields(),如果它返回一个空数组,则所有for块被跳过,映射_fields未初始化,并在调用null时保持_addFieldMixIns

发生这种情况是因为属性不是kotlin中的字段,并且父类没有属性。

可以通过向@JvmField类中添加NotificationEvent带注释的属性来解决此问题,如下所示:

sealed class NotificationEvent {

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

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

}

一切正常!

我希望这个问题能对某人有所帮助,并鼓励杰克逊团队修复此错误