记录一次Feign调用报JSON parse error的错(1、no suitable constructor found,2、Failed to parse Date)
在项目改造SpringCloud的时候,业务端调用服务端的时候,报JSON parse error的错。
feign.codec.DecodeException: JSON parse error: Can not construct instance of com.example.model.PageResult:
no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?);
nested exception is com.fasterxml.jackson.databind.JsonMappingException:
Can not construct instance of com.example.model.PageResult: no suitable constructor found,
can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: java.io.PushbackInputStream@3f8f1df2; line: 1, column: 52] (through reference chain: com.example.model.HttpResult["data"])
后来找到原因,是因为我的PageResult存在有参构造器却没有无参构造器。
public class PageResult<T> {
private int total = 0;
private List<T> list = null;
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
public PageResult(int total, List<T> list) {
this.total = total;
this.list = list;
}
}
加个无参构造器就好了。后来发现,Jackson需要创建一个类的实例,为了做到这一点,它需要类有一个无参构造函数。反序列化时,java类需要无参构造函数。
后来加上无参构造器,又报时间格式的错。
feign.codec.DecodeException: JSON parse error:
Can not deserialize value of type java.util.Date from String "2019-04-01 16:49:41":
not a valid representation (error: Failed to parse Date value '2019-04-01 16:49:41':
Can not parse date "2019-04-01 16:49:41": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSS', parsing fails (leniency? null));
nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException:
Can not deserialize value of type java.util.Date from String "2019-04-01 16:49:41":
not a valid representation (error: Failed to parse Date value '2019-04-01 16:49:41': Can not parse date "2019-04-01 16:49:41":
while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSS', parsing fails (leniency? null))
at [Source: java.io.PushbackInputStream@5ed6e6e5; line: 1, column: 150] (through reference chain:
com.djcps.example.model.HttpResult["data"]->com.example.model.PageResult["list"]->java.util.ArrayList[0]->com.example.model.response.ResQueryRegisterUser["createtime"])
原因是,jackson支持的时间格式有限的,它只支持:
"yyyy-MM-dd'T'HH:mm:ss.SSSZ"
"yyyy-MM-dd'T'HH:mm:ss.SSSZ"
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
"EEE, dd MMM yyyy HH:mm:ss zzz"
"yyyy-MM-dd"
而我用的是yyyy-MM-dd'T'HH:mm:ss
解决的办法是,自定义jackson解析时间格式yyy-MM-dd HH:mm:ss
/**
* @author: admin
* @date: 2019/05/17
* @description: 时间格式-使用装饰模式创建一个支持yyyy-MM-dd HH:mm:ss格式
*/
public class MyDateFormat extends DateFormat {
private DateFormat dateFormat;
private SimpleDateFormat format1 = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
public MyDateFormat(DateFormat dateFormat) {
this.dateFormat = dateFormat;
}
@Override
public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
return dateFormat.format(date, toAppendTo, fieldPosition);
}
@Override
public Date parse(String source, ParsePosition pos) {
Date date = null;
try {
date = format1.parse(source, pos);
} catch (Exception e) {
date = dateFormat.parse(source, pos);
}
return date;
}
/**
* 主要还是装饰这个方法
* @param source
* @return
* @throws ParseException
*/
@Override
public Date parse(String source) throws ParseException {
Date date = null;
try {
// 自定义原则
date = format1.parse(source);
} catch (Exception e) {
// 自定义原则异常就按原先的规则
date = dateFormat.parse(source);
}
return date;
}
/**
* 这里装饰clone方法的原因是因为clone方法在jackson中也有用到
*/
@Override
public Object clone() {
Object format = dateFormat.clone();
return new MyDateFormat((DateFormat) format);
}
}
添加bean:
@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
ObjectMapper mapper = jackson2ObjectMapperBuilder.build();
// ObjectMapper为了保障线程安全性,里面的配置类都是一个不可变的对象
// 所以这里的setDateFormat的内部原理其实是创建了一个新的配置类
DateFormat dateFormat = mapper.getDateFormat();
mapper.setDateFormat(new MyDateFormat(dateFormat));
return new MappingJackson2HttpMessageConverter(mapper);
}
参考文章:
版权声明:本文为m0_37772518原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。