Spring引导@RequestBody JsonMappingException但与@JsonCreator

时间:2017-08-06 08:02:57

标签: java json spring-boot resttemplate

您好我在Spring boot 1.5.4.RELEASE上构建了两个应用程序。 Application1 @RestController正在接受和反序列化JSON,没有例外。然后,Application1使用RestTemplate调用Application2 API。

应用1:

String json = "{\"tradeCurrency\":\"USD\",\"tradeAmount\":10.0,\"firstName\":\"test\",\"lastName\":\"test\",\"cardNum\":\"4485930029595000\",\"cardExpireMonth\":\"12\",\"cardExpireYear\":\"2021\",\"cvv\":\"123\",\"email\":\"fuxuboha@nutpa.net\",\"phoneNum\":\"8756756657\"}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(integrationPropertiesBean.getJsonRequestPayload(), headers);
String url = "http://localhost:8080/application2/test/testtransction";
ResponseEntity<Object> response = restTemplate.exchange(url, HttpMethod.POST, request, Object.class);

Application1 Logs:

[DEBUG] 2017-08-06 12:51:27.807 [http-nio-8080-exec-2] RequestAddCookies - CookieSpec selected: default
[DEBUG] 2017-08-06 12:51:27.808 [http-nio-8080-exec-2] RequestAuthCache - Auth cache not set in the context
[DEBUG] 2017-08-06 12:51:27.808 [http-nio-8080-exec-2] PoolingHttpClientConnectionManager - Connection request: [route: {}->http://localhost:8080][total kept alive: 0; route allocated: 0 of 5; total allocated: 0 of 10]
[DEBUG] 2017-08-06 12:51:27.808 [http-nio-8080-exec-2] PoolingHttpClientConnectionManager - Connection leased: [id: 1][route: {}->http://localhost:8080][total kept alive: 0; route allocated: 1 of 5; total allocated: 1 of 10]
[DEBUG] 2017-08-06 12:51:27.808 [http-nio-8080-exec-2] MainClientExec - Opening connection {}->http://localhost:8080/application2
[DEBUG] 2017-08-06 12:51:27.809 [http-nio-8080-exec-2] DefaultHttpClientConnectionOperator - Connecting to localhost/127.0.0.1:8080
[DEBUG] 2017-08-06 12:51:27.809 [http-nio-8080-exec-2] DefaultHttpClientConnectionOperator - Connection established 127.0.0.1:57458<->127.0.0.1:8080
[DEBUG] 2017-08-06 12:51:27.810 [http-nio-8080-exec-2] MainClientExec - Executing request POST /test/testtransction HTTP/1.1
[DEBUG] 2017-08-06 12:51:27.810 [http-nio-8080-exec-2] MainClientExec - Target auth state: UNCHALLENGED
[DEBUG] 2017-08-06 12:51:27.810 [http-nio-8080-exec-2] MainClientExec - Proxy auth state: UNCHALLENGED
[DEBUG] 2017-08-06 12:51:27.811 [http-nio-8080-exec-2] headers - http-outgoing-1 >> POST /test/testtransction HTTP/1.1
[DEBUG] 2017-08-06 12:51:27.811 [http-nio-8080-exec-2] headers - http-outgoing-1 >> Accept: application/json, application/json, application/*+json, application/*+json
[DEBUG] 2017-08-06 12:51:27.811 [http-nio-8080-exec-2] headers - http-outgoing-1 >> Content-Type: application/json
[DEBUG] 2017-08-06 12:51:27.811 [http-nio-8080-exec-2] headers - http-outgoing-1 >> Content-Length: 260
[DEBUG] 2017-08-06 12:51:27.811 [http-nio-8080-exec-2] headers - http-outgoing-1 >> Host: localhost:8080/application2
[DEBUG] 2017-08-06 12:51:27.811 [http-nio-8080-exec-2] headers - http-outgoing-1 >> Connection: Keep-Alive
[DEBUG] 2017-08-06 12:51:27.811 [http-nio-8080-exec-2] headers - http-outgoing-1 >> User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_111)
[DEBUG] 2017-08-06 12:51:27.812 [http-nio-8080-exec-2] headers - http-outgoing-1 >> Accept-Encoding: gzip,deflate
[DEBUG] 2017-08-06 12:51:27.812 [http-nio-8080-exec-2] wire - http-outgoing-1 >> "POST /test/testtransction HTTP/1.1[\r][\n]"
[DEBUG] 2017-08-06 12:51:27.812 [http-nio-8080-exec-2] wire - http-outgoing-1 >> "Accept: application/json, application/json, application/*+json, application/*+json[\r][\n]"
[DEBUG] 2017-08-06 12:51:27.812 [http-nio-8080-exec-2] wire - http-outgoing-1 >> "Content-Type: application/json[\r][\n]"
[DEBUG] 2017-08-06 12:51:27.812 [http-nio-8080-exec-2] wire - http-outgoing-1 >> "Content-Length: 260[\r][\n]"
[DEBUG] 2017-08-06 12:51:27.812 [http-nio-8080-exec-2] wire - http-outgoing-1 >> "Host: localhost:8080/application2[\r][\n]"
[DEBUG] 2017-08-06 12:51:27.812 [http-nio-8080-exec-2] wire - http-outgoing-1 >> "Connection: Keep-Alive[\r][\n]"
[DEBUG] 2017-08-06 12:51:27.812 [http-nio-8080-exec-2] wire - http-outgoing-1 >> "User-Agent: Apache-HttpClient/4.5.3 (Java/1.8.0_111)[\r][\n]"
[DEBUG] 2017-08-06 12:51:27.813 [http-nio-8080-exec-2] wire - http-outgoing-1 >> "Accept-Encoding: gzip,deflate[\r][\n]"
[DEBUG] 2017-08-06 12:51:27.813 [http-nio-8080-exec-2] wire - http-outgoing-1 >> "[\r][\n]"
[DEBUG] 2017-08-06 12:51:27.813 [http-nio-8080-exec-2] wire - http-outgoing-1 >> ""{\"tradeCurrency\":\"USD\",\"tradeAmount\":10.0,\"firstName\":\"test\",\"lastName\":\"test\",\"cardNum\":\"4485930029595000\",\"cardExpireMonth\":\"12\",\"cardExpireYear\":\"2021\",\"cvv\":\"123\",\"email\":\"fuxuboha@nutpa.net\",\"phoneNum\":\"8756756657\"}""

应用2:

@RestController
@RequestMapping("/test")
public class SimulatorIntegrationController {
    @RequestMapping(value = "testtransction", method = RequestMethod.POST)
    public TestResponse testTransaction(@RequestBody Test test) {
        System.out.println("testTransaction == "+test);
        TestResponse response = new TestResponse();
        response.setResponseMessage("test");
        response.setStatus("Approved");
        response.setTxn_no("221434324");
        response.setTxn_response_code("100");
        System.out.println("Transaction2DResponse ::: "+response);
        return response;
    }
}

Application2 log:

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not construct instance of com.test.bean.Test: no String-argument constructor/factory method to deserialize from String value ('{"currency":"USD","amount":10.0,"firstName":"test","lastName":"test","cardNum":"4485930029595000","cardExpireMonth":"12","cardExpireYear":"2021","cvv":"123","email":"fuxuboha@nutpa.net","phoneNum":"8756756657"}'); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.test.bean.Test: no String-argument constructor/factory method to deserialize from String value ('{"currency":"USD","amount":10.0,"firstName":"test","lastName":"test","cardNum":"4485930029595000","cardExpireMonth":"12","cardExpireYear":"2021","cvv":"123","email":"fuxuboha@nutpa.net","phoneNum":"8756756657"}')
at [Source: java.io.PushbackInputStream@6d65317e; line: 1, column: 1]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:244)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:229)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:201)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:150)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:128)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.test.bean.Test: no String-argument constructor/factory method to deserialize from String value ('{"currency":"USD","amount":10.0,"firstName":"test","lastName":"test","cardNum":"4485930029595000","cardExpireMonth":"12","cardExpireYear":"2021","cvv":"123","email":"fuxuboha@nutpa.net","phoneNum":"8756756657"}')
at [Source: java.io.PushbackInputStream@6d65317e; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270)
at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:1456)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1012)
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:370)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:315)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1283)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:159)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:150)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3798)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2922)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:241)
... 55 more

我无法理解为什么Application2正在发生这种情况,而Application1与JSON一起工作正常。我后来发现了一些解决这个问题的方法。我在Application2 Test bean中添加了@JsonCreator,用作@RequestBody。添加@JsonCreator后,此问题得到解决。

@JsonCreator
public static Test Create(String jsonString) {
    System.out.println("@JsonCreator Test");
    System.out.println(jsonString);
    Test test = null;
    try {
        ObjectMapper mapper = new ObjectMapper();
        test = mapper.readValue(jsonString, Test.class);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return test;
}

但我想知道为什么没有@JsonCreator就失败了。我希望它在没有@JsonCreator的情况下工作。

注意: 我按照以下方式尝试Curl到Application2 API,没有例外。

curl -i -X POST -H 'Content-Type: application/json' -d '{ "tradeCurrency ": "USD ", "tradeAmount ":10.0, "firstName ": "test ", "lastName ": "test ", "cardNum ": "4485930029595000 ", "cardExpireMonth ": "12 ", "cardExpireYear ": "2021 ", "cvv ": "123 ", "email ": "fuxuboha@nutpa.net ", "phoneNum ": "8756756657 "}' http://localhost:8080/application2/test/testtransction

1 个答案:

答案 0 :(得分:0)

我再次检查了代码,发现GsonHttpMessageConverter已添加到MessageConvertersRestTemplate。我删除它,一切都开始工作了。 我删除了下面提到的代码。

final List<HttpMessageConverter<?>> listHttpMessageConverters = new ArrayList< HttpMessageConverter<?> >(); 
listHttpMessageConverters.add(new GsonHttpMessageConverter());
restTemplate.setMessageConverters(listHttpMessageConverters);