我正在使用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", ....}
我查看了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行为的方法吗?
答案 0 :(得分:2)
这是一个错误;我打开了JIRA Issue。
我认为,唯一的解决方法是在本地修复错误(子类ObjectToJsonTransformer
,通过删除doTransform()
调用来修复populateJavaTypes
)并替换<object-to-json-transformer/>
正常<transformer/>
引用您的bean。
填充java类型标题为added in 3.0。