近期在工作中有接触到 MySQL5.7 新增的 Json 存储格式。
之前存储这种 1 对多的可扩展对象都是使用 jsonstr 以 varchar 格式保存。在接触到 json 格式之后,本以为是更加方便,结果出现了一个大问题,在国内网上找资料怎么都是找不到原因(可能是我搜索的方式不对)。在这里记录一下这个事件。
背景:
当 json 对象的值以字符串格式存储的时候,会以 json{"id":id,"jsonParam":"jsonParam"}的形式保存。然后这时候在进行取值的时候,如果使用 jsonName ->'$.jsonParam' as jsonParam
或者 JSON_EXTRACT(jsonName,'$.jsonParam') as jsonParam
的时候会返回
id | jsonParam |
---|---|
id | "jsonParam" |
也就是说返回的结果也会附带“"” 这个时候在 Service 层要处理数据就需要先进行相关的转换。 | |
然而 Json 格式的返回值,无论使用 trim() 还是 JSON_UNQUOTE() 都会出现本地或工具运行时可以看到值,而使用程序的 mybaties 赋值给接收的 JSONObject 对象时,debug 发现总是取不到值的问题。 |
|
处理: | |
使用 debug 时,发现返回值都有 key,但是 value 全是空的,而且奇怪的是,value 中是有对象的,而且有时候还会呈现数组的那种形式。 | |
于是使用 log 方式将这个接收的对象以 jsonStr 的方式打印出来,发现里面的值并不是预想的 String 类型。 | |
进行返回值的类型确认,发现这个值的类型属于 byte[] , 黑人问号.gif | |
网上各种查资料,有的说是数据库 Connection 的版本问题,可是在升级到 5.1.40 之后仍然无法解决这个问题。。。。。。看起来应该是属于其他的问题导致。 | |
迫于项目的紧急性,之后线将程序功能写出来,后面再慢慢探究其缘由。 | |
不过既然知道返回的数据类型了,就可以很好的进行处理了。 | |
目前想到的方案有 2: | |
1、mysql 不进行“"”的处理,收到返回值后,使用字符串替换掉“"”。 | |
2、继续在 mysql 中进行“"”的处理,返回值再进行 byte[]的处理。 | |
理论上俩个都是可行的,不过方案 2 相当于多进行了一次数据处理。(以我目前的 LV 还不能确定哪个更优。) | |
注:JSON_UNQUOTE(JSON_EXTRACT(jsonName,'$.jsonParam')) 等价 <![CDATA[jsonName -> '$.jsonParam']]> |
|
不过我选择的还是第二种方案,原因是我“没法确定”json 的属性值中是否含有自带的“"”(不过其实在当前需求进行 mysql 的表结构设计的时候,是不会出现某个 json 属性为另一个 json 对象 即 {id:id,obj:{id:id}}这种结构。但是为了后面新增功能时少修改的东西,还是使用稳妥的方案 2 看起来更加靠谱。 | |
sql: |
<!--<![CDATA[ select AUTHORITY->>'$.flag' flag , AUTHORITY->>'$.ids' ids ]]> from com_position where ID in <foreach collection="positionIds" open="(" item="positionId" separator="," close=")">#{positionId,jdbcType=VARCHAR}</foreach>>-->
<![CDATA[ select AUTHORITY->>'$.flag' flag , AUTHORITY->>'$.ids' ids ]]> from com_position where ID in <foreach collection="positionIds" open="(" item="positionId" separator="," close=")">#{positionId,jdbcType=VARCHAR}</foreach>>
// 因为json取值多出“"” 使用替换
// String tmp = authority.getString("ids").replaceAll("\"","");
// authority.put("ids",tmp);
// tmp=authority.getString("flag").replaceAll("\"","");
// authority.put("flag",tmp);
if(authority.get("ids") instanceof byte[]){
byte[] bytes = (byte[])authority.get("ids");
try {
String tt = new String(bytes,"UTF-8");
authority.put("ids",tt);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
同时也希望有大神能留言告诉小弟,为什么这里使用 JSON_UNQUOTE 和 trim 会且都会变成 byte[]的类型
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于