欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

fastjson对Timestamp的处理 解决:For input string: "2019-10-21 14:05:21"

程序员文章站 2022-06-15 12:10:38
...

场景:fastjson处理json与java对象转换十分方便,现在有需求需要使用fastjson的 JSON.toJavaObject(json,clazz)方法

将json数据转为SubReport对象,SubReport subReport = JSON.toJavaObject(json, SubReport.class);,其中SubReport的时间对象使用的是java.sql.TimeStamp,转换过程中抛出异常For input string: "2019-10-21 14:05:21"。

解决方法:

    将字符串转化为java.util.Date,然后交给fastjson进行转换即可,代码如下:

public static void testJson() throws Exception{
		JSONObject json = new JSONObject();

		json.put("addtime","2019-10-21 14:05:21");
		json.put("edittime","2019-09-21 14:05:22");
		json.put("addUsername","张飞");
		json.put("editUsername","赵云");

		//将字符串形式的时间,转为Date格式,fastjson内部支持Date转TimeStamp
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date addtime = sdf.parse(json.getString("addtime"));
		json.put("addtime",addtime);

		System.out.println("转换前参数:"+json.toJSONString());
		SubReport subReport = JSON.toJavaObject(json, SubReport.class);

		System.out.println("转换后修改时间为:"+subReport.getEdittime());
		System.out.println("转换后添加时间为:"+subReport.getAddtime());

		System.out.println("对象转json:"+JSON.toJSONString(subReport));
	}

 

代码及原理 :

SubReport 对象为:

package com.putorn.powerdoc.entity;

import com.alibaba.fastjson.annotation.JSONField;

import java.sql.Timestamp;
import java.util.Date;

public class SubReport {
    // 添加人id
    private Integer addUserid;
    // 添加人姓名
    private String addUsername;
    // 添加时间
    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private Timestamp addtime;
    // 修改人id
    private Integer editUserid;
    // 修改人姓名
    private String editUsername;
    // 修改时间
    @JSONField(format="yyyy-MM-dd HH:mm:ss")
    private Date edittime;

    public Integer getAddUserid() {
        return addUserid;
    }

    public void setAddUserid(Integer addUserid) {
        this.addUserid = addUserid;
    }

    public String getAddUsername() {
        return addUsername;
    }

    public void setAddUsername(String addUsername) {
        this.addUsername = addUsername;
    }

    public Timestamp getAddtime() {
        return addtime;
    }

    public void setAddtime(Timestamp addtime) {
        this.addtime = addtime;
    }

    public Integer getEditUserid() {
        return editUserid;
    }

    public void setEditUserid(Integer editUserid) {
        this.editUserid = editUserid;
    }

    public String getEditUsername() {
        return editUsername;
    }

    public void setEditUsername(String editUsername) {
        this.editUsername = editUsername;
    }

    public Date getEdittime() {
        return edittime;
    }

    public void setEdittime(Date edittime) {
        this.edittime = edittime;
    }
}

 

跟踪fastjson源码,可以找到内部转换时对Timestamp的处理方法(具体代码追踪需耐心查看并理解,下面只给出源码及与本问题相关的代码注释):com\alibaba\fastjson\1.2.12\fastjson-1.2.12.jar!\com\alibaba\fastjson\util\TypeUtils.class 第430行:

	
/**
*这是fastjson内部转换TimeStamp类型的数据时使用的,当反射获取的java类字段类型为 java.sql.Timestamp时,转换调用此方法
*/
	
	public static java.sql.Timestamp castToTimestamp(Object value) {
        if (value == null) {
            return null;
        }

//支持日历类转换
        if (value instanceof Calendar) {
            return new java.sql.Timestamp(((Calendar) value).getTimeInMillis());
        }

        if (value instanceof java.sql.Timestamp) {
            return (java.sql.Timestamp) value;
        }

//如果是Date类型,则直接new一个java.sql.Timestamp
        if (value instanceof java.util.Date) {
            return new java.sql.Timestamp(((java.util.Date) value).getTime());
        }

        long longValue = 0;

// fastjson支持数字格式转换为Timestamp,(不加注解的话用java bean转json时默认也是将Timestamp转为:Number)
        if (value instanceof Number) {
            longValue = ((Number) value).longValue();
        }

//如果是字符串,判断非空非null
        if (value instanceof String) {
            String strVal = (String) value;
            if (strVal.length() == 0 //
                || "null".equals(strVal) //
                || "NULL".equals(strVal)) {
                return null;
            }

//直接将字符串转换为Long类型(这里可以看出fastjson只支持
//数字的字符串类型,不支持Date,Calendar等的字符串类型)
//例如 "1571637921000"可以,而"2019-10-21 14:05:21"则跑出转换异常 :For input string:
            longValue = Long.parseLong(strVal);
        }

        if (longValue <= 0) {
            throw new JSONException("can not cast to Date, value : " + value);
        }

        return new java.sql.Timestamp(longValue);
    }

 

另外,java实体类中的注解 

@JSONField(format="yyyy-MM-dd HH:mm:ss")作用是规定fastjson转换为java bean对象时的格式

加上注解,打印报文为:

对象转json:{"addUsername":"张飞","addtime":"2019-10-21 14:05:21","editUsername":"赵云","edittime":"2019-09-21 14:05:22"}  格式良好,

不加,则报文为:对象转json:{"addUsername":"张飞","addtime":1571637921000,"editUsername":"赵云","edittime":1569045922000}

可以看出,不加的话java.sql.Timestamp格式和java.util.Date格式的字段都被转换成了数字类型!