本文介绍了在Spring Integration中将JSON转换为对象数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在从服务(http出站网关)以json格式返回对象数组,我们需要将其序列化回对象/POJOS数组.首先,我们尝试通过将XML配置设置为

We are returning an array of objects from a service (http outbound gateway) in json format and we need it serialized back into an array of objects/POJOS. First we tried simply serializing the POJO without any array lists by setting the XML configuration to

<int:json-to-object-transformer input-channel="testJsonToObjectChannel"
            output-channel="testChannel" type="com.that.service.service.test.ApplicationTestDomain" />

,并且转换器和http出站网关都返回相同的对象.但是,将其转换为"ApplicationTestDomain" POJO数组之后,我们在堆栈跟踪中发现了其中特别提到的错误

and had both the transformer and the http outbound gateway return the same object. However after converting it to an array of "ApplicationTestDomain" POJOs we are getting the error mentioned in the stack trace where it notably mentions

"No converter found capable of converting from type java.util.ArrayList<?> to type com.that.service.service.test.ApplicationTestDomain"

我们还尝试了一个简单的字符串数组,并且也成功地对其进行了序列化和反序列化,只有在我们尝试对对象数组进行序列化和反序列化时,才会出现此问题.

We also tried a simple array of strings and they were succesfully serialized and deserialzed as well, the issue only comes up when we try to serialize and deserialize an array of objects.

关于需要做什么才能解决的任何想法

Any idea on what needs to be done so that can be resolved

以下是返回数组列表的服务

The following is the service which returns the array list

@Service("applicationTestService")
public class ApplicationTestService {

    private static Logger logger = Logger.getLogger(ApplicationTestService.class);

    public ArrayList<ApplicationTestDomain> getTestThatData(Message<?> inMessage){
        ArrayList<ApplicationTestDomain> testData = new ArrayList<ApplicationTestDomain>();

        ApplicationTestDomain testDomain = new ApplicationTestDomain();
        testDomain.setId(1L);
        testDomain.setTotalPrice(100.00D);
        testDomain.setTotalTaxes(70.00D);
        testDomain.setTotalAll(70D);

        testData.add(testDomain);

        return testData;
    }

}

以下是接收数组列表的服务

The following is the service which receives the array list

@MessageEndpoint("applicationDataTransformer")
public class ApplicationTransformer {

    public ApplicationResponse transformData(ArrayList<ApplicationTestDomain> response) {
        return new ApplicationResponse();
    }
}

以下是xml配置

<int-http:outbound-gateway request-channel="applicationConfigurationRequest"
                           reply-channel="testJsonToObjectChannel"
                           url="http://localhost:8080/testapplication/services/application/testService"
                           http-method="GET"
                           expected-response-type="java.lang.String"/>


<int:json-to-object-transformer input-channel="testJsonToObjectChannel"
        output-channel="testChannel" type="java.util.ArrayList" />

<int:transformer input-channel="testChannel"
    ref="applicationDataTransformer"
    method="transformData"
    output-channel="applicationConfigurationResponse"/>

以下是异常堆栈跟踪

at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.messaging.MessageHandlingException: org.springframework.expression.AccessException: Problem invoking method: public com.that.domain.service.hotelavailability.HotelAvailabilityResponse com.that.transformer.service.ApplicationTransformer.transformData(java.util.ArrayList)
    at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:78)
    at org.springframework.integration.transformer.AbstractMessageProcessingTransformer.transform(AbstractMessageProcessingTransformer.java:64)
    at org.springframework.integration.transformer.MessageTransformingHandler.handleRequestMessage(MessageTransformingHandler.java:68)
    ... 83 more
Caused by: org.springframework.expression.AccessException: Problem invoking method: public com.that.domain.service.hotelavailability.HotelAvailabilityResponse com.that.transformer.service.ApplicationTransformer.transformData(java.util.ArrayList)
    at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:67)
    at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:122)
    at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:44)
    at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:258)
    at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:84)
    at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:114)
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:111)
    at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:159)
    at org.springframework.integration.util.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:268)
    at org.springframework.integration.util.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:142)
    at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:75)
    ... 85 more
Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.util.ArrayList<?> to type java.util.ArrayList<com.that.service.service.test.ApplicationTestDomain> for value '[{id=1, totalPrice=100.0, totalTaxes=70.0, totalAll=70.0}]'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type java.util.ArrayList<?> to type com.that.service.service.test.ApplicationTestDomain
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174)
    at org.springframework.integration.util.BeanFactoryTypeConverter.convertValue(BeanFactoryTypeConverter.java:123)
    at org.springframework.expression.spel.support.ReflectionHelper.convertArguments(ReflectionHelper.java:240)
    at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:57)
    ... 95 more
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type java.util.ArrayList<?> to type com.that.service.service.test.ApplicationTestDomain
    at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:291)
    at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:177)
    at org.springframework.core.convert.support.CollectionToCollectionConverter.convert(CollectionToCollectionConverter.java:85)
    at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:35)
    ... 99 more

关于,MilindaD

Regards,MilindaD

推荐答案

您在这里遇到的问题是,您仅使用原始的java.util.ArrayList,最终仅使用ArrayList<LinkedHashMap<String, Object>>而不是ArrayList<LinkedHashMap<String, ApplicationTestDomain>>.

Your issues here that you just use raw java.util.ArrayList and you end up just with ArrayList<LinkedHashMap<String, Object>>, rather than ArrayList<LinkedHashMap<String, ApplicationTestDomain>>.

尝试这个技巧:

type="com.that.service.service.test.ApplicationTestDomain[]"

此处的一般要点是我们无法为Class提供通用规范.

The general stop here that we can't provide Class with generic specification.

但是使用该数组技巧,当Framework将Message应用于服务方法的参数时,应该自动将Array转换为Collection.

But with that array trick there should automatic conversion from Array to Collection when Framework appies Message to arguments of your service method.

从另一面<int-http:outbound-gateway>提供expected-response-type-expression,它可以返回ParameterizedTypeReference<?>.

From other side <int-http:outbound-gateway> provides expected-response-type-expression, which can return ParameterizedTypeReference<?>.

这是一个技巧,如何让他知道您想要的类型:

Here is a trick how to let him know about your desired type:

<int:header-enricher>
        <int:header name="expectedResponseType">
            <int-groovy:script>
                <![CDATA[
                    new org.springframework.core.ParameterizedTypeReference<List<com.that.service.service.test.ApplicationTestDomain>>() {}
                ]]>
            </int-groovy:script>
        </int:header>
</int:header-enricher>

<int-http:outbound-gateway request-channel="applicationConfigurationRequest"
                       reply-channel="testJsonToObjectChannel"
                       url="http://localhost:8080/testapplication/services/application/testService"
                       http-method="GET"
                       expected-response-type-expression="headers.expectedResponseType"/>

具有此功能,您当然可以允许RestTemplate使用Jackson将响应转换为所需值.从这里开始,没有更多的理由使用<int:json-to-object-transformer>,因为您已经有了POJO列表.

Having this you allow to RestTemplate to convert response to the desired value using Jackson, of course. And from here there is no more reason to use <int:json-to-object-transformer>, because you already have your List of POJOs.

这篇关于在Spring Integration中将JSON转换为对象数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 03:51