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 + '\'' +
                '}';
    }
}
posted @ 2019-12-12 14:47  kelelipeng  阅读(2129)  评论(0编辑  收藏  举报