JFinal4.9设置JsonDatePattern无效的问题

版本JFinal4.9

现有代码:

@Override
public void configConstant(Constants me) {
  me.setJsonDatePattern("yyyy-MM-dd");
  JFinalJson.setModelAndRecordFieldNameToCamelCase();
  me.setJsonFactory(MixedJsonFactory.me());
}

数据库create_time字段类型为datetime,映射的Java model已确认为java.util.Date,以下为BaseXXX的相关代码

public M setCreateTime(java.util.Date createTime) {
 set("create_time", createTime);
 return (M)this;
}

public java.util.Date getCreateTime() {
 return get("create_time");
}

现象:无论修改me.setJsonDatePattern("yyyy-MM-dd");为什么格式,返回的json字段都是yyyy-MM-dd HH:mm:ss格式

相关源码分析:

JFinalJson

@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public String toJson(Object object) {
 if (object == null) {
  return "null";
 }
 
 JsonResult ret = TL.get();
 try {
  // 优先使用对象级的属性 datePattern, 然后才是全局性的 defaultDatePattern
  String dp = datePattern != null ? datePattern : getDefaultDatePattern();
  ret.init(dp, timestampPattern);
  ToJson toJson = kit.getToJson(object);
  toJson.toJson(object, convertDepth, ret);
  return ret.toString();
 }
 finally {
  ret.clear();
 }
}

JFinalJsonKit

if (value instanceof java.util.Date) {
 if (value instanceof Timestamp) {
  return new TimestampToJson();
 }
 if (value instanceof Time) {
  return new TimeToJson();
 }
 return new DateToJson();
}

调试:

image.png

调试发现createTime被作为Timestamp处理了,而timestampPattern的值目前无法修改,因为MixedJson.getJFinalJson()为private方法,也就没办法获取这个内部实例调用setTimestampPattern()

建议me.setJsonDatePattern("yyyy-MM-dd");的时候同时设置defaultDatePattern和timestampPattern都为这个值,这样子更常用一些,或者退而求其次开放设置JFinalJson.timestampPattern的方法,即修改MixedJson.getJFinalJson()为public方法

评论区

JFinal

2020-06-03 17:04

jfinal 4.9 重新设计了 JFinalJson 模块,采用了全方位扩展结构,所以要实现你这个功能极度简单:
JFinalJson.addToJson(Timestamp.class, (v, d, ret) -> {
Timestamp t = (Timestamp)v;
String s = ret.getFormat("yyyy-MM-dd").format(t);
ret.addStrNoEscape(s);
});

由于 Json.java 中并不支持 timestampPattern 配置,所以该配置仅仅是 JFinalJson 内部使用的,所以你当前无法简单地通过配置解决问题

在你不扩展的情况下,只可以临时指令 timestampPattern,例如:
JFinalJson.getJson().setTimestampPattern(...).toJson(...);

上面的临时指定不是全局配置,需要每次都要调用一下那个 setTimestampPattern

JFinal

2020-06-03 17:05

通过 JFinalJson.addToJson(Timestamp.class, (v, d, ret) -> {}); 这种扩展方式,你可以针对任意类型去定制转换规则

没有比这更彻底、简单、舒爽的扩展方式了

Dull

2020-06-03 17:06

可是JFinalJson有.setTimestampPattern(...)方法,只需要开放MixedJson.getJFinalJson()为public方法就可以全局修改了呀

JFinal

2020-06-03 17:07

@Dull 那个配置仍然只是局部的, 用我介绍的配置方法才能成为全局的

Dull

2020-06-03 17:09

@JFinal 我是觉得数据库datetime类型为极其常用的类型,仅仅设置me.setJsonDatePattern("yyyy-MM-dd");就同时修改岂不是更贴近开发者的使用特,对于一些不常用的数据库类型可以用定制

JFinal

2020-06-03 17:12

@Dull 使用 Timestamp 的情况,一般是需要 时、分、秒的, 所以 JFinalJson 的默认配置就挺好用的

你的需求是不需要 时、分、秒,所以,我建议你使用 mysql 的 date 类型,而不是 datetime 类型,因为有些浪费

Dull

2020-06-03 17:16

@JFinal 一般数据库存储的时间当然更为精确,会具体到时、分、秒,前端展示则是另外一回事,不然将来需要更具体的时间就GG了,当前先用JFinalJson.addToJson(Timestamp.class, (v, d, ret) -> {});去解决我的需求

JFinal

2020-06-03 17:18

@Dull 用上 JFinalJson.addToJson 挺好的

AlienJunX

2020-06-04 10:37

你提的需求应该是传统Java开发者的需求, 换成这种闭包形式语法上可能有点不是很习惯吧