1. 程式人生 > >fastjson對於yyyy-MM-dd HH:mm格式的反序列化問題

fastjson對於yyyy-MM-dd HH:mm格式的反序列化問題

問題:最近在工作中遇到這麼一個問題:有個實體類,它有個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 + '\'' +
                '}';
    }
}