Json字符串格式的Model反序列化为Model时候,类型丢失问题?

天生蛋疼菊紧 发布于 2015/04/22 14:45
阅读 978
收藏 0

@JFinal 你好,想跟你请教个问题:

波总,再次请教您。我这边场景是这样的,c/s桌面程序,从client发出请求到server端,请求的数据都是序列化后的Json,但是现在有一个问题,Json到达java服务端后,反序列化时候,Model中原始的属性类型丢失了。

比如datetime日期变更了字符串,float,double变成了bigdecimal格式。这个类型变异导致的结果是,我无法准确的拿到model的准确类型,使用model的基础方法, 如getfloat,getdate全部报错,需要借助工具类先将数据tostring,再Float.valueof提取到我需要的float数据,但是如此依赖,代码不够优雅,而且有不必要碎片。

在开源中国上已经看到有开发者提出了解决办法,链接如下 http://my.oschina.net/taijunfeng/blog/354181?p={{page}}

我参考这个开发者的解决思路,在json反序列为model的时候,拿到JFinal缓存下来的talbe meta,对字段类型进行修正。但是又发现了新的问题。以下是我一个表中,检测到属性 和类型的映射关系

在我圈起来的地方,数据库用的类型是smallint,然后我查看到JFinal映射到smallint类型是String,

如此依赖,在修正Model类型的时候,凡是数据库字段是smallint的就无法准确修正类型。需要在get属性值的时候,做额外处理。

请问这个,smallint格式无法准确映射到short类型是Jfinal的一个bug吗?期待您的回复。

加载中
1
天生蛋疼菊紧
天生蛋疼菊紧

引用来自“JFinal”的评论

public void testTypes() throws SQLException {
  String sql = DbKit.config.getDialect().forTableBuilderDoBuild("jfinal");
  Statement stm = DbKit.config.getConnection().createStatement();
  ResultSet rs = stm.executeQuery(sql);
  ResultSetMetaData rsmd = rs.getMetaData();

  for (int i=1; i<=rsmd.getColumnCount(); i++) {
    String colName = rsmd.getColumnName(i);
    String colClassName = rsmd.getColumnClassName(i);
    print(rsmd, i);
  }
}

public void print(ResultSetMetaData rsmd, int i) throws SQLException {
int type = rsmd.getColumnType(i);
if (type == Types.BLOB)
System.out.println(rsmd.getColumnLabel(i) + " ---> BLOB --->" + rsmd.getColumnClassName(i));
else if (type == Types.VARCHAR)
System.out.println(rsmd.getColumnLabel(i) + " ---> VARCHAR --->" + rsmd.getColumnClassName(i));
else if (type == Types.INTEGER)
System.out.println(rsmd.getColumnLabel(i) + " ---> INTEGER --->" + rsmd.getColumnClassName(i));
else if (type == Types.BINARY)
System.out.println(rsmd.getColumnLabel(i) + " ---> BINARY --->" + rsmd.getColumnClassName(i));
else if (type == Types.SMALLINT)
System.out.println(rsmd.getColumnLabel(i) + " ---> SMAILLINT --->" + rsmd.getColumnClassName(i));
else if (type == Types.DATE)
System.out.println(rsmd.getColumnLabel(i) + " ---> DATE --->" + rsmd.getColumnClassName(i));
else if (type == Types.TIME)
System.out.println(rsmd.getColumnLabel(i) + " ---> TIME --->" + rsmd.getColumnClassName(i));
else if (type == Types.TIMESTAMP)
System.out.println(rsmd.getColumnLabel(i) + " ---> TIMESTAMP --->" + rsmd.getColumnClassName(i));
else if (type == Types.BIGINT)
System.out.println(rsmd.getColumnLabel(i) + " ---> BIGINT --->" + rsmd.getColumnClassName(i));
else if (type == Types.TINYINT)
System.out.println(rsmd.getColumnLabel(i) + " ---> TINYINT --->" + rsmd.getColumnClassName(i));
else if (type == Types.BIT)
System.out.println(rsmd.getColumnLabel(i) + " ---> BIT --->" + rsmd.getColumnClassName(i));
else if (type == Types.DOUBLE)
System.out.println(rsmd.getColumnLabel(i) + " ---> DOUBLE --->" + rsmd.getColumnClassName(i));
else if (type == Types.DECIMAL)
System.out.println(rsmd.getColumnLabel(i) + " ---> DECIMAL --->" + rsmd.getColumnClassName(i));
else if (type == Types.CHAR)
System.out.println(rsmd.getColumnLabel(i) + " ---> CHAR --->" + rsmd.getColumnClassName(i));
else if (type == Types.REAL)
System.out.println(rsmd.getColumnLabel(i) + " ---> REAL --->" + rsmd.getColumnClassName(i));
else if (type == Types.VARBINARY)
System.out.println(rsmd.getColumnLabel(i) + " ---> VARBINARY --->" + rsmd.getColumnClassName(i));
else if (type == Types.LONGVARBINARY)
System.out.println(rsmd.getColumnLabel(i) + " ---> LONGVARBINARY --->" + rsmd.getColumnClassName(i));
else if (type == Types.LONGVARCHAR)
System.out.println(rsmd.getColumnLabel(i) + " ---> LONGVARCHAR --->" + rsmd.getColumnClassName(i));
else
System.out.println("没找到类型: type ---> " + type + rsmd.getColumnClassName(i));
}
多谢波总, 谢谢你回复。是试试,有问题会随时向你反馈。:)
0
JFinal
JFinal

    刚刚我在本地测试了一下,mysql 的 smallint 映射为了 java 的 Integer 类型,并且在 Model.getInt(String) 方法的注释中也有过说明,如下:

调试一下,类型错误是在哪个环节发生的

0
天生蛋疼菊紧
天生蛋疼菊紧

引用来自“JFinal”的评论

    刚刚我在本地测试了一下,mysql 的 smallint 映射为了 java 的 Integer 类型,并且在 Model.getInt(String) 方法的注释中也有过说明,如下:

调试一下,类型错误是在哪个环节发生的

你好,谢谢你的回复。忘了给你说了。我这边用的数据库是sql server
上面那个属性和类型映射截图,显示的是typeMap的结果。sql server 数据库smallint类型映射到的类型是String
// 获取table的元数据
     Table table = TableMapping.me().getTable(clazz);
// 得到属性类型的map
     Map<String, Class<?>> typeMap = table.getColumnTypeMap();





期待你的回复
JFinal
JFinal
sql server 的话,去群里找个有环境的人测试一下,程序我在下面给出,我本地没有 sql server 环境
0
JFinal
JFinal
public void testTypes() throws SQLException {
  String sql = DbKit.config.getDialect().forTableBuilderDoBuild("jfinal");
  Statement stm = DbKit.config.getConnection().createStatement();
  ResultSet rs = stm.executeQuery(sql);
  ResultSetMetaData rsmd = rs.getMetaData();

  for (int i=1; i<=rsmd.getColumnCount(); i++) {
    String colName = rsmd.getColumnName(i);
    String colClassName = rsmd.getColumnClassName(i);
    print(rsmd, i);
  }
}

public void print(ResultSetMetaData rsmd, int i) throws SQLException {
int type = rsmd.getColumnType(i);
if (type == Types.BLOB)
System.out.println(rsmd.getColumnLabel(i) + " ---> BLOB --->" + rsmd.getColumnClassName(i));
else if (type == Types.VARCHAR)
System.out.println(rsmd.getColumnLabel(i) + " ---> VARCHAR --->" + rsmd.getColumnClassName(i));
else if (type == Types.INTEGER)
System.out.println(rsmd.getColumnLabel(i) + " ---> INTEGER --->" + rsmd.getColumnClassName(i));
else if (type == Types.BINARY)
System.out.println(rsmd.getColumnLabel(i) + " ---> BINARY --->" + rsmd.getColumnClassName(i));
else if (type == Types.SMALLINT)
System.out.println(rsmd.getColumnLabel(i) + " ---> SMAILLINT --->" + rsmd.getColumnClassName(i));
else if (type == Types.DATE)
System.out.println(rsmd.getColumnLabel(i) + " ---> DATE --->" + rsmd.getColumnClassName(i));
else if (type == Types.TIME)
System.out.println(rsmd.getColumnLabel(i) + " ---> TIME --->" + rsmd.getColumnClassName(i));
else if (type == Types.TIMESTAMP)
System.out.println(rsmd.getColumnLabel(i) + " ---> TIMESTAMP --->" + rsmd.getColumnClassName(i));
else if (type == Types.BIGINT)
System.out.println(rsmd.getColumnLabel(i) + " ---> BIGINT --->" + rsmd.getColumnClassName(i));
else if (type == Types.TINYINT)
System.out.println(rsmd.getColumnLabel(i) + " ---> TINYINT --->" + rsmd.getColumnClassName(i));
else if (type == Types.BIT)
System.out.println(rsmd.getColumnLabel(i) + " ---> BIT --->" + rsmd.getColumnClassName(i));
else if (type == Types.DOUBLE)
System.out.println(rsmd.getColumnLabel(i) + " ---> DOUBLE --->" + rsmd.getColumnClassName(i));
else if (type == Types.DECIMAL)
System.out.println(rsmd.getColumnLabel(i) + " ---> DECIMAL --->" + rsmd.getColumnClassName(i));
else if (type == Types.CHAR)
System.out.println(rsmd.getColumnLabel(i) + " ---> CHAR --->" + rsmd.getColumnClassName(i));
else if (type == Types.REAL)
System.out.println(rsmd.getColumnLabel(i) + " ---> REAL --->" + rsmd.getColumnClassName(i));
else if (type == Types.VARBINARY)
System.out.println(rsmd.getColumnLabel(i) + " ---> VARBINARY --->" + rsmd.getColumnClassName(i));
else if (type == Types.LONGVARBINARY)
System.out.println(rsmd.getColumnLabel(i) + " ---> LONGVARBINARY --->" + rsmd.getColumnClassName(i));
else if (type == Types.LONGVARCHAR)
System.out.println(rsmd.getColumnLabel(i) + " ---> LONGVARCHAR --->" + rsmd.getColumnClassName(i));
else
System.out.println("没找到类型: type ---> " + type + rsmd.getColumnClassName(i));
}
返回顶部
顶部