Spring 4中的ObjectToJsonTransformer在具有空值时抛出NPE

时间:2016-06-06 12:10:08

标签: java json spring spring-integration

我正在使用spring集成处理JSON消息。消息的格式可能不同,我对我收到的整个JSON的特定子对象(称为payload)感兴趣。我将该子对象的Java类与接收到的消息中的另一个字段(type)进行匹配,以便知道如何对其进行反序列化。

为实现这一点,我使用java.lang.Object将消息转换为<int:json-to-object-transformer type="java.lang.Object" /> - 这实际上会将初始JSON转换为LinkedMap对象,我可以查询字段并执行过滤和我的spring集成xml中的路由 - 例如:

<int:recipient-list-router input-channel="jsonInputChannel" ignore-send-failures="false" default-output-channel="fallbackChannel">
  <int:recipient 
    channel="validInputChannel" 
    selector-expression="payload.containsKey('type') and payload.containsKey('payload')"/>
</int:recipient-list-router>

在上文中,payload被视为Map个对象。然后我提取我需要的相关对象,以进一步转换为特定的Java类:

<int:chain input-channel="validInputChannel" output-channel="objectResolveChannel">
    <int:transformer expression="payload.get('payload')" />
    <int:object-to-json-transformer />
</int:chain>

当消息的有效负载属性如{"field1": null, "field2": "something", ....}

时,我正在获取NPE

我查看了Spring 4.2.4.RELEASE源代码,我可以看到ObjectToJsonTransformer调用this.jsonObjectMapper.populateJavaTypes(headers, message.getPayload()); 这按顺序调用JsonObjectMapperAdapter中的方法实现,如下所示:

public void populateJavaTypes(Map<String, Object> map, Object object) {
    map.put(JsonHeaders.TYPE_ID, object.getClass());
    if (object instanceof Collection && !((Collection) object).isEmpty()) {
        map.put(JsonHeaders.CONTENT_TYPE_ID, ((Collection) object).iterator().next().getClass());
    }
    if (object instanceof Map && !((Map) object).isEmpty()) {
        map.put(JsonHeaders.CONTENT_TYPE_ID, ((Map) object).values().iterator().next().getClass());
        map.put(JsonHeaders.KEY_TYPE_ID, ((Map) object).keySet().iterator().next().getClass());
    }
}

您可以看到,当对象被视为Map实例时,代码在地图值的第一个元素上使用getClass(),但这当然可以是null,因此NPE是抛出。

我们之前使用Spring 3.2.1.RELEASE和Spring Integration 2.2.6.RELEASE,并且完全相同的Spring集成XML配置。据我所知,上面有问题的代码在Spring 3中没有出现。

有人可以为这个问题提出一个很好的解决方法或者回到Spring 3行为的方法吗?

1 个答案:

答案 0 :(得分:2)

这是一个错误;我打开了JIRA Issue

我认为,唯一的解决方法是在本地修复错误(子类ObjectToJsonTransformer,通过删除doTransform()调用来修复populateJavaTypes)并替换<object-to-json-transformer/>正常<transformer/>引用您的bean。

填充java类型标题为added in 3.0