如何解决JavaScript传JSON到Java时Timestamp类型不兼容错误?
问题
前端通过JavaScript向Java后端发送包含日期的JSON请求体时,出现类型不兼容错误:
org.apache.struts2.json.JSONException: Incompatible types for property setBillingDate
相关代码如下:
JSP代码
<div class="inv-row"> <span class="labels-alignment inv-label">Invoice Date: </span> <input type="text" id="dtPaymentDate" style="height: 30px;background-color: #fff; cursor: pointer; max-width: 185px;" onblur="dateFieldBlur(this)" class="form-control dp" placeholder="mm/dd/yyyy" required ng-model="dtPaymentDate"> <span class="text-danger fade in" style="width: 100%; float: left; position: relative; margin-top: 5px;">{{paymentDateError}} {{paymentGreaterDueDateError}}</span> </div> <div class="inv-row"> <span class="labels-alignment inv-label">Due Date: </span> <input type="text" id="dtDuePaymentDate" style="height: 30px;background-color: #fff; cursor: pointer; max-width: 185px;" onblur="dateFieldBlur(this)" class="form-control dp" placeholder="mm/dd/yyyy" required ng-model="dtDuePaymentDate"> <span class="text-danger fade in" style="width: 100%; float: left; position: relative; margin-top: 5px;">{{dueDateError}}</span> </div>
JavaScript代码
jQuery('#dtPaymentDate').val(this.objScope.PaymentDate); jQuery('#dtDuePaymentDate').val(this.objScope.DueDate); var reqParams = { userId: this.objScope.userId, billingDate : this.objScope.PaymentDate, billingDueDate : this.objScope.DueDate }; var strFunctionToCall = "javaController.action" + "?" + "action=processFormCall"; this.makeCall(strFunctionToCall, reqParams,this.processFormStartComplete.bind(this), this.processFormStartComplete.bind(this));
Java后端接收字段
private Timestamp billingDate; private Timestamp billingDueDate;
解决方案
方法一:前端转换日期格式为后端可识别的标准格式
前端传递的mm/dd/yyyy字符串无法被Struts2的JSON插件直接转换为Timestamp,可转换为ISO 8601格式或时间戳(毫秒数):
转ISO格式示例:
// 把mm/dd/yyyy字符串转为ISO格式 function formatDateToISO(dateStr) { const [month, day, year] = dateStr.split('/'); return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}T00:00:00`; } var reqParams = { userId: this.objScope.userId, billingDate : formatDateToISO(this.objScope.PaymentDate), billingDueDate : formatDateToISO(this.objScope.DueDate) };
转时间戳示例:
// 把mm/dd/yyyy字符串转为时间戳(毫秒) function getTimestamp(dateStr) { const [month, day, year] = dateStr.split('/'); return new Date(year, month - 1, day).getTime(); } var reqParams = { userId: this.objScope.userId, billingDate : getTimestamp(this.objScope.PaymentDate), billingDueDate : getTimestamp(this.objScope.DueDate) };
后端Timestamp可直接接收时间戳(若为秒级时间戳需乘以1000)。
方法二:后端修改字段处理逻辑
临时转换:将字段改为String,在setter中手动转换
修改后端字段类型为String,在setter方法中把字符串转为Timestamp:private Timestamp billingDate; public void setBillingDate(String billingDateStr) throws ParseException { // 匹配前端的mm/dd/yyyy格式 SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy"); Date date = sdf.parse(billingDateStr); this.billingDate = new Timestamp(date.getTime()); }需处理
ParseException,或添加全局异常处理。使用Struts2自定义类型转换器
实现Struts2的TypeConverter接口,自定义日期到Timestamp的转换逻辑,再在配置文件中注册:- 编写转换器类:
public class TimestampConverter extends StrutsTypeConverter { private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM/dd/yyyy"); @Override public Object convertFromString(Map context, String[] values, Class toClass) { if (values == null || values.length == 0 || StringUtils.isEmpty(values[0])) { return null; } try { Date date = DATE_FORMAT.parse(values[0]); return new Timestamp(date.getTime()); } catch (ParseException e) { throw new RuntimeException("日期转换失败", e); } } @Override public String convertToString(Map context, Object o) { if (o instanceof Timestamp) { return DATE_FORMAT.format((Timestamp) o); } return ""; } } - 在
xwork-conversion.properties中配置:java.sql.Timestamp=com.yourpackage.TimestampConverter
- 编写转换器类:
方法三:配置Struts2 JSON插件的日期格式
在Struts2配置文件中指定JSON插件的日期转换格式,匹配前端传递的mm/dd/yyyy:
<package name="default" extends="json-default"> <action name="javaController" class="com.yourpackage.JavaController"> <result type="json"> <param name="dateFormat">MM/dd/yyyy</param> <param name="root">result</param> </result> </action> </package>
此方式可让JSON插件自动按指定格式将字符串转为Timestamp。
内容的提问来源于stack exchange,提问作者Alyan Ahmed
相关产品推荐
相关产品推荐

