問題:最近在工作中遇到這麼一個問題:有個實體類,它有個date類型的屬性,當在這個屬性加上fastjson的註解@JSONField (format=”yyyy-MM-dd HH:mm”)將秒去掉後,對象轉換成json字符串,再用這個字符串反過來轉換成對象的時候去報錯了。如圖所示:
查看源碼後得知是fastjson在處理這個日期格式時並沒有考慮到這個問題。好在fastjson可以擴展,我們可以通過繼承DateFormatDeserializer去實現我們自己的反序列化器來解析這個格式。
記錄一下解決辦法以便今後查詢,當然,這不一定就是正確的解決辦法,如果有更好的解決辦法歡迎給我留言。
解決辦法:我們要自己去實現自己的Deserializer
這裏我取了個巧,參考了fastjson的util包中TypeUtils類的castToDate方法了。。。。
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.deserializer.DateFormatDeserializer;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* Created by gray on 2017/3/12.
*/
public class MyDateFormatDeserializer extends DateFormatDeserializer {
@Override
protected <T> T cast(DefaultJSONParser parser, Type clazz, Object fieldName, Object value) {
if(value == null) {
return null;
} else if(value instanceof Calendar) {
return (T) ((Calendar)value).getTime();
} else if(value instanceof Date) {
return (T) value;
} else {
long longValue = -1L;
if(value instanceof Number) {
longValue = ((Number)value).longValue();
return (T) new Date(longValue);
} else {
if(value instanceof String) {
String strVal = (String)value;
if(strVal.indexOf(45) != -1) {
String format;
if(strVal.length() == 10) {
format = "yyyy-MM-dd";
} else if(strVal.length() == "yyyy-MM-dd HH:mm".length()) {
format = "yyyy-MM-dd HH:mm";
} else if(strVal.length() == "yyyy-MM-dd HH:mm:ss".length()) {
format = "yyyy-MM-dd HH:mm:ss";
} else {
format = "yyyy-MM-dd HH:mm:ss.SSS";
}
SimpleDateFormat dateFormat = new SimpleDateFormat(format);
try {
return (T) dateFormat.parse(strVal);
} catch (ParseException var7) {
throw new JSONException("can not cast to Date, value : " + strVal);
}
}
if(strVal.length() == 0) {
return null;
}
longValue = Long.parseLong(strVal);
}
if(longValue < 0L) {
throw new JSONException("can not cast to Date, value : " + value);
} else {
return (T) new Date(longValue);
}
}
}
}
}
測試:在我們要使用的地方這麼寫,如下代碼:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import java.util.Date;
/**
* Created by gray on 2017/3/12.
*/
public class Test {
static ParserConfig config = new ParserConfig();
public static void main(String args[]) {
String json = "{oneDate:'2017-03-14 20:25',twoDate:'2017-03-14 21:30:12',text:'test'}";
config.putDeserializer(Date.class, new MyDateFormatDeserializer()); // 我們自己實現的Deserializer
TestBean bean = JSON.parseObject(json,TestBean.class, config, JSON.DEFAULT_PARSER_FEATURE, new Feature[0]);
System.out.print(bean.toString());
}
}
parseObject這個方法平時我們用得多的就是String和class兩個參數,其實它後面會默認調用多參的方法,放入默認的配置而已。這樣寫然後運行結果就正確了,MyDateFormatDeserializer裏面該處理的格式都處理清楚就不會影響別的date格式了(onedate和twodate格式互不影響,如果你的MyDateFormatDeserializer只處理了”yyyy-MM-dd HH:mm”這一種格式會導致twodate的精度丟失)。運行結果如圖所示:
最後附上TestBean
import java.util.Date;
/**
* Created by gray on 2017/3/12.
*/
public class TestBean {
private Date oneDate;
private Date twoDate;
private String text;
public Date getOneDate() {
return oneDate;
}
public void setOneDate(Date oneDate) {
this.oneDate = oneDate;
}
public Date getTwoDate() {
return twoDate;
}
public void setTwoDate(Date twoDate) {
this.twoDate = twoDate;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
@Override
public String toString() {
return "TestBean{" +
"oneDate=" + oneDate +
", twoDate=" + twoDate +
", text='" + text + '\'' +
'}';
}
}