mysql在5.6版本时,不支持直接Json存储,我们一般存储成varchar
等string类型。编码时,我们也是将数据json格式化后,存储。
从5.7版开始,开始支持JSON格式存储,那么在使用Go存储对应的字段时,如何定义struct,就是一个问题。现有orm一般没有支持json类型的定义。如果struct定义为string
类型,会导致一些问题。例如JSON数据为空时,存储的是””, 有时候会导致一些差别。
例如使用gorm存储数据时,不支持Json类型的数据结构。
为解决这个问题,我们可以自定义一个JSON的struct
Mysql结构
如在Mysql中定义了如下的表结构
1 2 3 4 5 6 7 8 9 10
| CREATE TABLE `report` ( `id` bigint(20) NOT NULL, `query_param` json DEFAULT NULL, `create_by` varchar(50) DEFAULT NULL COMMENT '创建人', `create_date` timestamp NULL DEFAULT NULL COMMENT '创建时间', `update_by` varchar(50) DEFAULT NULL COMMENT '修改人', `update_date` timestamp NULL DEFAULT NULL COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `id_UNIQUE` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
过去我们会定义query_param
为varchar
等字符串类型,在mysql 5.7中我们可以直接定义为json
类型
自定义JSON类型
这样我们在orm中定义struct时,就会遇到问题。
过去我们会将Json字段定义为string
1 2 3 4 5 6 7 8 9
| type Report struct { ID int64 `json:"id"` QueryParam string `json:"queryParam"` CreateBy string `json:"createBy"` CreateDate time.Time `json:"createDate"` UpdateBy string `json:"updateBy"` UpdateDate time.Time `json:"updateDate"` }
|
但这样在存储数据时,是有些差别的。如果queryParam
为空时,此时存储为””,非NULL。与我们的设计是不同的。
为解决这个问题,可以自定义一个JSON类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| package models
import ( "bytes" "database/sql/driver" "errors" )
type JSON []byte
func (j JSON) Value() (driver.Value, error) { if j.IsNull() { return nil, nil } return string(j), nil }
func (j *JSON) Scan(value interface{}) error { if value == nil { *j = nil return nil } s, ok := value.([]byte) if !ok { errors.New("Invalid Scan Source") } *j = append((*j)[0:0], s...) return nil }
func (m JSON) MarshalJSON() ([]byte, error) { if m == nil { return []byte("null"), nil } return m, nil }
func (m *JSON) UnmarshalJSON(data []byte) error { if m == nil { return errors.New("null point exception") } *m = append((*m)[0:0], data...) return nil }
func (j JSON) IsNull() bool { return len(j) == 0 || string(j) == "null" }
func (j JSON) Equals(j1 JSON) bool { return bytes.Equal([]byte(j), []byte(j1)) }
|
这样我们在定义models时,可以指定为JSON
类型
1 2 3 4 5 6 7 8 9
| type Report struct { ID int64 `json:"id"` QueryParam JSON `json:"queryParam"` CreateBy string `json:"createBy"` CreateDate time.Time `json:"createDate"` UpdateBy string `json:"updateBy"` UpdateDate time.Time `json:"updateDate"` }
|
参考文章
原文golang-gorm框架支持mysql json类型