mysql在5.6版本时,不支持直接Json存储,我们一般存储成varchar等string类型。编码时,我们也是将数据json格式化后,存储。
从5.7版开始,开始支持JSON格式存储,那么在使用Go存储对应的字段时,如何定义struct,就是一个问题。现有orm一般没有支持json类型的定义。如果struct定义为string类型,会导致一些问题。例如JSON数据为空时,存储的是””, 有时候会导致一些差别。
例如使用gorm存储数据时,不支持Json类型的数据结构。
为解决这个问题,我们可以自定义一个JSON的struct
Mysql结构
如在Mysql中定义了如下的表结构
| 12
 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
| 12
 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类型
| 12
 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类型
| 12
 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类型