使用Go+sqlx从MySQL检索JSON列数据时遇扫描错误求助
Go + sqlx 读取MySQL JSON列扫描报错解决方案
问题背景
MySQL中data列存储的JSON结构如下:
[{"name": "Abc", "ids": [108, 33, 34, 35]}]
使用sqlx执行查询时触发错误:
sql: Scan error on column index 0, name "data": unsupported Scan, storing driver.Value type []uint8 into type *[]test.Data
核心原因
MySQL驱动将JSON列以[]uint8(字节数组)格式返回,sqlx无法自动完成该类型到自定义[]Data切片的映射,需要手动实现类型转换逻辑。
方案1:为自定义切片实现sql.Scanner接口
通过为[]Data创建包装类型并实现sql.Scanner接口,让sqlx能自动完成JSON解析:
步骤1:定义包装类型并实现接口
import ( "database/sql/driver" "encoding/json" "fmt" ) // DataList 包装[]Data类型,用于实现SQL扫描接口 type DataList []Data // Scan 实现sql.Scanner接口,处理MySQL返回的JSON字节数组 func (d *DataList) Scan(value interface{}) error { bytes, ok := value.([]byte) if !ok { return fmt.Errorf("invalid data type for JSON column: expected []byte, got %T", value) } return json.Unmarshal(bytes, d) } // Value 实现driver.Valuer接口(可选,若需要写入JSON列时使用) func (d DataList) Value() (driver.Value, error) { return json.Marshal(d) }
步骤2:修改结构体字段类型
将原来的[]Data替换为DataList:
type MainResponse struct { Data DataList `db:"data"` Field1 string `db:"field1"` Field2 string `db:"field2"` } type DataStruct struct { Data DataList `db:"data"` Field1 string `db:"field1"` Field2 string `db:"field2"` } type Data struct { Name store.NullString `db:"name"` Ids []int `db:"ids"` }
修改后,原查询代码无需改动,sqlx会自动调用Scan方法完成JSON解析。
方案2:手动扫描后解析JSON
若不想修改结构体类型,可先将JSON列扫描为原始字节类型,再手动解析:
步骤1:修改结构体字段类型
type DataStruct struct { Data json.RawMessage `db:"data"` // 或使用[]byte类型 Field1 string `db:"field1"` Field2 string `db:"field2"` }
步骤2:查询后手动解析JSON
sqlstr := `SELECT field1, field2, data FROM myTable` records := []DataStruct{} err := store.DB().Select(&records, sqlstr) if err != nil { return nil, err } mainResponses := []MainResponse{} for _, entry := range records { var dataList []Data if err := json.Unmarshal(entry.Data, &dataList); err != nil { return nil, err } mainResponses = append(mainResponses, MainResponse{ Field1: entry.Field1, Field2: entry.Field2, Data: dataList, }) }
这种方式更灵活,适合临时场景或无需频繁写入JSON列的情况。
内容的提问来源于stack exchange,提问作者girish
相关产品推荐
相关产品推荐

