调用服务异常Jackson日期转换异常-Error while extracting response for type...省略...while it seems to fit format

本文详细分析了在自动化单元测试中遇到的JSON日期格式解析错误,并提供了具体的解决方案。通过修改实体类中的日期字段注解,确保了JSON日期格式与实体类字段格式一致,解决了测试中的异常。

写自动化单元测试用例的时候出错, 错误信息:

 

2018-10-03 20:41:47.099  INFO 10068 --- [           main] com.imooc.util.RestUtil                  : rest-post-json-请求参数:<{"id":"T001","name":"灵活宝1号","status":"AUDITING","thresholdAmount":10,"stepAmount":1,"lockTerm":null,"rewardRate":3.42,"memo":null,"createAt":null,"updateAt":null,"createUser":null,"updateUser":null},{Content-Type=[application/json;charset=UTF-8], Accept=[application/json]}>
2018-10-03 20:41:47.368  INFO 10068 --- [o-auto-1-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-10-03 20:41:47.370  INFO 10068 --- [o-auto-1-exec-2] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2018-10-03 20:41:47.423  INFO 10068 --- [o-auto-1-exec-2] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 53 ms
2018-10-03 20:41:47.540  INFO 10068 --- [o-auto-1-exec-2] c.i.m.controller.ProductController       : 增加产品, 参数:com.imooc.entity.Product@db6d71b[id=T001,name=灵活宝1号,status=AUDITING,thresholdAmount=10,stepAmount=1,lockTerm=<null>,rewardRate=3.42,memo=<null>,createAt=<null>,updateAt=<null>,createUser=<null>,updateUser=<null>]
2018-10-03 20:41:47.559  INFO 10068 --- [o-auto-1-exec-2] c.imooc.manager.service.ProductService   : 创建产品, 参数:com.imooc.entity.Product@db6d71b[id=T001,name=灵活宝1号,status=AUDITING,thresholdAmount=10,stepAmount=1,lockTerm=<null>,rewardRate=3.42,memo=<null>,createAt=<null>,updateAt=<null>,createUser=<null>,updateUser=<null>]
Hibernate: select product0_.id as id1_1_0_, product0_.create_at as create_a2_1_0_, product0_.create_user as create_u3_1_0_, product0_.lock_term as lock_ter4_1_0_, product0_.memo as memo5_1_0_, product0_.name as name6_1_0_, product0_.reward_rate as reward_r7_1_0_, product0_.status as status8_1_0_, product0_.step_amount as step_amo9_1_0_, product0_.threshold_amount as thresho10_1_0_, product0_.update_at as update_11_1_0_, product0_.update_user as update_12_1_0_ from product product0_ where product0_.id=?
Hibernate: insert into product (create_at, create_user, lock_term, memo, name, reward_rate, status, step_amount, threshold_amount, update_at, update_user, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
2018-10-03 20:41:47.814  INFO 10068 --- [o-auto-1-exec-2] c.imooc.manager.service.ProductService   : 创建产品, 结果:com.imooc.entity.Product@587f46ea[id=T001,name=灵活宝1号,status=AUDITING,thresholdAmount=10,stepAmount=1,lockTerm=0,rewardRate=3.42,memo=<null>,createAt=Wed Oct 03 20:41:47 CST 2018,updateAt=Wed Oct 03 20:41:47 CST 2018,createUser=<null>,updateUser=<null>]
2018-10-03 20:41:47.814  INFO 10068 --- [o-auto-1-exec-2] c.i.m.controller.ProductController       : 增加产品, 结果:com.imooc.entity.Product@587f46ea[id=T001,name=灵活宝1号,status=AUDITING,thresholdAmount=10,stepAmount=1,lockTerm=0,rewardRate=3.42,memo=<null>,createAt=Wed Oct 03 20:41:47 CST 2018,updateAt=Wed Oct 03 20:41:47 CST 2018,createUser=<null>,updateUser=<null>]
2018-10-03 20:41:47.943  INFO 10068 --- [           main] o.s.t.c.transaction.TransactionContext   : Rolled back transaction for test context [DefaultTestContext@139982de testClass = ProductControllerTest, testInstance = com.imooc.manager.controller.ProductControllerTest@6f15d60e, testMethod = create@ProductControllerTest, testException = org.springframework.web.client.RestClientException: Error while extracting response for type [class com.imooc.entity.Product] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.Date` from String "2018-10-03 20:41:47": not a valid representation (error: Failed to parse Date value '2018-10-03 20:41:47': Cannot parse date "2018-10-03 20:41:47": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null)); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date` from String "2018-10-03 20:41:47": not a valid representation (error: Failed to parse Date value '2018-10-03 20:41:47': Cannot parse date "2018-10-03 20:41:47": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null))
 at [Source: (PushbackInputStream); line: 1, column: 147] (through reference chain: com.imooc.entity.Product["createAt"]), mergedContextConfiguration = [WebMergedContextConfiguration@682b2fa testClass = ProductControllerTest, locations = '{}', classes = '{class com.imooc.manager.ManagerApp}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=0}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@262b2c86, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@50d0686, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@b7dd107, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@75881071], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> false]].

org.springframework.web.client.RestClientException: Error while extracting response for type [class com.imooc.entity.Product] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.Date` from String "2018-10-03 20:41:47": not a valid representation (error: Failed to parse Date value '2018-10-03 20:41:47': Cannot parse date "2018-10-03 20:41:47": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null)); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date` from String "2018-10-03 20:41:47": not a valid representation (error: Failed to parse Date value '2018-10-03 20:41:47': Cannot parse date "2018-10-03 20:41:47": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null))
 at [Source: (PushbackInputStream); line: 1, column: 147] (through reference chain: com.imooc.entity.Product["createAt"])

	at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:115)
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:732)
	at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:686)
	at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:437)
	at com.imooc.util.RestUtil.postJSON(RestUtil.java:31)
	at com.imooc.manager.controller.ProductControllerTest.lambda$create$0(ProductControllerTest.java:59)
	at java.util.ArrayList.forEach(ArrayList.java:1249)
	at com.imooc.manager.controller.ProductControllerTest.create(ProductControllerTest.java:58)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
	at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.Date` from String "2018-10-03 20:41:47": not a valid representation (error: Failed to parse Date value '2018-10-03 20:41:47': Cannot parse date "2018-10-03 20:41:47": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null)); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date` from String "2018-10-03 20:41:47": not a valid representation (error: Failed to parse Date value '2018-10-03 20:41:47': Cannot parse date "2018-10-03 20:41:47": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null))
 at [Source: (PushbackInputStream); line: 1, column: 147] (through reference chain: com.imooc.entity.Product["createAt"])
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:241)
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:223)
	at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:100)
	... 38 more
Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date` from String "2018-10-03 20:41:47": not a valid representation (error: Failed to parse Date value '2018-10-03 20:41:47': Cannot parse date "2018-10-03 20:41:47": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null))
 at [Source: (PushbackInputStream); line: 1, column: 147] (through reference chain: com.imooc.entity.Product["createAt"])
	at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
	at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1548)
	at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:910)
	at com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseDate(StdDeserializer.java:524)
	at com.fasterxml.jackson.databind.deser.std.StdDeserializer._parseDate(StdDeserializer.java:467)
	at com.fasterxml.jackson.databind.deser.std.DateDeserializers$DateBasedDeserializer._parseDate(DateDeserializers.java:195)
	at com.fasterxml.jackson.databind.deser.std.DateDeserializers$DateDeserializer.deserialize(DateDeserializers.java:285)
	at com.fasterxml.jackson.databind.deser.std.DateDeserializers$DateDeserializer.deserialize(DateDeserializers.java:268)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:369)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3072)
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:235)
	... 40 more

2018-10-03 20:41:47.963  INFO 10068 --- [       Thread-3] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@22bac7bc: startup date [Wed Oct 03 20:41:37 CST 2018]; root of context hierarchy
2018-10-03 20:41:47.970  INFO 10068 --- [       Thread-3] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2018-10-03 20:41:47.971  INFO 10068 --- [       Thread-3] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2018-10-03 20:41:47.984  INFO 10068 --- [       Thread-3] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

Process finished with exit code -1

注意这个错误信息:

 Error while extracting response for type [class com.imooc.entity.Product] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.Date` from String "2018-10-03 20:41:47": not a valid representation (error: Failed to parse Date value '2018-10-03 20:41:47': Cannot parse date "2018-10-03 20:41:47": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null)); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date` from String "2018-10-03 20:41:47": not a valid representation (error: Failed to parse Date value '2018-10-03 20:41:47': Cannot parse date "2018-10-03 20:41:47": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null))

分析如下:

"Error while extracting response for type "拉取响应类型时出错,
 "JSON parse error: Cannot deserialize value of type `java.util.Date` ", 很明显无法解析这个日期类型

我的工具类如下:

 /**
     * 发送post 请求
     *
     * @param restTemplate
     * @param url
     * @param param
     * @param responseType
     * @param <T>
     * @return
     */
    public static <T> T postJSON(RestTemplate restTemplate, String url, Object param, Class<T> responseType) {
        HttpEntity<String> formEntity = makePostJSONEntiry(param);
        T result = restTemplate.postForObject(url, formEntity, responseType);
        log.info("rest-post-json 响应信息:{}", JsonUtil.toJson(result));
        return result;
    }

    /**
     * 生成json形式的请求头
     *
     * @param param
     * @return
     */
    public static HttpEntity<String> makePostJSONEntiry(Object param) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);
        HttpEntity<String> formEntity = new HttpEntity<String>(
                JsonUtil.toJson(param), headers);
        log.info("rest-post-json-请求参数:{}", formEntity.toString());
        return formEntity;
    }

因为jackson在转换数据的时候默认是 'yyyy-MM-dd'T'HH:mm:ss.SSSZ,这样的类型,

修改Product实体类, 加上如下注解即可

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Entity
public class Product {

    /** 创建时间 */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createAt;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    /** 更新时间 */
    private Date updateAt;

 

因为如下原因: 在调用postJSON请求方式的时候, 创建的是 yyyy-MM-dd HH:mm:ss 格式的日期,  而用 Product result 接收的时候,经过了我的代码中 toJson--> return mapper.writeValueAsString(obj); 转换了, 所以就变成yyyy-MM-dd'T'HH:mm:ss.SSSZ, 就出错了

@Test
@Transactional
public void create(){
    normals.forEach(product -> {
        Product result = RestUtil.postJSON(restTemplate,baseUrl + "/products",product,Product.class);
        Assert.notNull(result.getName(),"创建产品失败");
    });
}

 

 

当Feign接口调用出现 `error while extracting response for type... and content type [application/json]` 异常时,可尝试以下解决办法: ### 检查响应数据与目标类型是否匹配 确保服务端返回的JSON数据结构与Feign客户端期望接收的类型一致。例如,如果服务端返回的是JSON数组,而客户端期望的是单个对象,就会出现转换异常。 ```java // 假设服务端返回JSON数组 // 错误示例:期望单个对象 @FeignClient(name = "example-service") public interface ExampleFeignClient { @GetMapping("/data") ExampleData getData(); } // 正确示例:期望数组 @FeignClient(name = "example-service") public interface ExampleFeignClient { @GetMapping("/data") List<ExampleData> getData(); } ``` ### 检查JSON解析器配置 Feign默认使用Jackson进行JSON解析,确保Jackson配置正确,并且能够处理服务端返回的JSON数据。可以自定义Feign的解码器来配置Jackson。 ```java import feign.codec.Decoder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import feign.jackson.JacksonDecoder; @Configuration public class FeignConfig { @Bean public Decoder feignDecoder() { return new JacksonDecoder(new MappingJackson2HttpMessageConverter()); } } ``` ### 确保实体类有合适的构造函数 如果实体类没有无参构造函数或者合适的反序列化构造函数,Jackson在解析JSON数据时会报错。确保实体类有默认的无参构造函数,或者提供带有必要参数的构造函数并使用 `@JsonCreator` 和 `@JsonProperty` 注解。 ```java import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class ExampleData { private String name; private int age; @JsonCreator public ExampleData(@JsonProperty("name") String name, @JsonProperty("age") int age) { this.name = name; this.age = age; } // Getters and setters public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } ``` ### 处理响应状态码 如果服务端返回的状态码不是200,Feign可能会抛出异常。可以自定义错误解码器来处理不同的状态码。 ```java import feign.Response; import feign.codec.ErrorDecoder; import org.springframework.stereotype.Component; @Component public class CustomErrorDecoder implements ErrorDecoder { @Override public Exception decode(String methodKey, Response response) { // 处理不同的状态码 switch (response.status()) { case 400: // 处理400错误 break; case 404: // 处理404错误 break; default: return new Exception("Generic error"); } return null; } } ``` ### 检查服务端响应内容 确保服务端返回的JSON数据格式正确,没有语法错误。可以使用工具(如Postman)直接调用服务端接口,查看返回的JSON数据。 ### 检查依赖版本 确保Feign、Spring Cloud等相关依赖的版本兼容。不同版本的依赖可能存在兼容性问题,导致JSON解析异常
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值