Golang使用sqlx写入MySQL JSON字段数组被转义为字符串如何解决
问题场景
需要向MySQL中插入JSON对象,原始实现代码如下:
array := []string{"BT", "TL", "CN"} s, err := json.Marshal(array) if err != nil { return err } _, err := db.Exec("update setting set multilingual = json_set(multilingual, '$.supported', ?) where id = ?", s, 10) if err != nil { return err }
预期数据库中multilingual字段的存储结果为:
{"supported": ["BT","TL","CN"]}
实际写入后得到的结果为:
{"supported": "[\"BT\",\"TL\",\"CN\"]"}
运行环境为使用sqlx作为Golang连接MySQL的依赖库,需要修复该写入异常问题。
问题原因
Go中json.Marshal序列化切片得到的是JSON格式的字节序列,直接将该值作为参数传入JSON_SET函数时,MySQL会将其判定为普通字符串类型,而非JSON结构值,因此存储时会自动对字符串中的引号做转义,最终将路径下的值存为转义后的字符串,而非预期的JSON数组。
修复方法
修改SQL语句,对传入的序列化JSON参数做显式类型转换,告知MySQL将该值作为JSON类型解析,只需要给参数包裹CAST(? AS JSON)即可,修正后的代码如下:
array := []string{"BT", "TL", "CN"} s, err := json.Marshal(array) if err != nil { return err } // 显式将传入参数转换为JSON类型,避免被识别为普通字符串 _, err := db.Exec("update setting set multilingual = json_set(multilingual, '$.supported', CAST(? AS JSON)) where id = ?", s, 10) if err != nil { return err }
执行上述代码后,写入结果就会和预期一致,$.supported路径下存储的是原生JSON数组,不会出现额外的转义字符。
该方案无需调整Go侧序列化逻辑,也不需要更换数据库驱动,仅修改SQL语句即可生效,兼容原生database/sql、sqlx等所有常用Go MySQL连接库。
内容的提问来源于stack exchange,提问作者Tony Cheng
相关产品推荐
相关产品推荐

