Golang查询MySQL时如何正确读取映射表中的JSON类型字段
问题原因
直接给rows.Scan()传&batcher.UserInformation扫不出来数据很正常:Go标准库database/sql默认不认自定义结构体,不知道怎么把MySQL返回的JSON类型值自动塞到你的UserInformation结构里。MySQL返回的JSON字段本质就是一段JSON格式的字节流,没法直接映射成你定义的结构体实例。
解决方法
不用装第三方库,两步就能搞定:
- 扫库的时候先拿个
[]byte类型的临时变量接住userInformation字段的原始内容 - 用标准库
encoding/json把这段字节流反序列化到batcher.UserInformation字段里就行
修正后的完整代码
先确保导入了encoding/json包,修改后的查询逻辑如下:
import ( "encoding/json" "net/http" "github.com/gin-gonic/gin" ) func getBatchers(c *gin.Context) { var batchers []BatchersData // 按表实际字段查询全量数据,也可以直接用SELECT * rows, err := db.Query("SELECT Profile, userInformation, badge FROM Batchers_page_db") if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } defer rows.Close() for rows.Next() { var batcher BatchersData // 临时变量存JSON字段的原始字节 var userInfoRaw []byte // 注意参数顺序和SQL查询返回的字段顺序一一对应 if err := rows.Scan(&batcher.ProfileURL, &userInfoRaw, &batcher.Badge); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } // 把JSON字节反序列化到结构体字段 if err := json.Unmarshal(userInfoRaw, &batcher.UserInformation); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } batchers = append(batchers, batcher) } if err := rows.Err(); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.IndentedJSON(http.StatusOK, batchers) }
可选优化(一劳永逸)
如果不想每次查这个字段都手动写反序列化逻辑,可以给UserInformation结构体实现sql.Scanner接口,之后扫库直接传&batcher.UserInformation即可,不需要临时变量。实现代码如下(需要额外导入errors包):
import "errors" func (u *UserInformation) Scan(value interface{}) error { byteData, ok := value.([]byte) if !ok { return errors.New("userInformation字段类型断言为[]byte失败") } // 自动完成JSON反序列化 return json.Unmarshal(byteData, u) }
实现该接口后,rows.Scan()部分可以直接写成:
if err := rows.Scan(&batcher.ProfileURL, &batcher.UserInformation, &batcher.Badge); err != nil { // 错误处理逻辑 }
内容的提问来源于stack exchange,提问作者Arjun Malhotra
相关产品推荐
相关产品推荐

