gorm中正确的使用json数据类型

一、说明

  • 1、JSON 数据类型是 MySQL 5.7.8 开始支持的。在此之前,只能通过字符类型(CHARVARCHARTEXT )来保存 JSON 文档。现实中也很多人不会采用json的存储方式,直接定义一个字符类型,让前端转换传递进来,返回给前端也是一个字符串,前端自己处理

  • 2、json数据类型参考文档

  • 3、创建一个数据表

    CREATE TABLE `report` (
      `id` int NOT NULL AUTO_INCREMENT COMMENT '主键id',
      `query_param` json NOT NULL,
      `name` varchar(50) DEFAULT NULL,
      `created_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '创建时间',
      `updated_at` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新时间',
      `deleted_at` timestamp(6) NULL DEFAULT NULL COMMENT '软删除时间',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
    

二、gorm中使用json方式一

  • 1、自定义数据类型

    // JSON 自定义JSON数据类型
    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))
    }
    
  • 2、在配置生成实体类的工具中遇到json的话直接转换为JSON数据类型

    dataMap := map[string]func(detailType gorm.ColumnType) (dataType string){
    	"json":      func(detailType gorm.ColumnType) (dataType string) { return "JSON" },      // 自定义	
    }
    
  • 3、逆向生成的实体类

    type ReportEntity struct {
    	ID         int64          `gorm:"column:id;type:int;primaryKey;autoIncrement:true;comment:主键id" json:"id"` // 主键id
    	QueryParam JSON           `gorm:"column:query_param;type:json;not null" json:"queryParam"`
    	Name       string         `gorm:"column:name;type:varchar(50)" json:"name"`
    	CreatedAt  LocalTime      `gorm:"column:created_at;comment:创建时间" json:"createdAt"`            // 创建时间
    	UpdatedAt  LocalTime      `gorm:"column:updated_at;comment:更新时间" json:"updatedAt"`            // 更新时间
    	DeletedAt  gorm.DeletedAt `gorm:"column:deleted_at;type:timestamp(6);comment:软删除时间" json:"-"` // 软删除时间
    }
    
  • 4、定义DTO的时候直接定义JSON数据类型

    type Test1Dto struct {
    	QueryParam JSON `json:"queryParam"`
    	Name       string         `json:"name"`
    }
    
  • 5、随便插入数据

    gorm中正确的使用json数据类型_第1张图片

三、定义JSON的方式二

  • 1、直接使用gorm自带的json数据类型datatypes.JSON
  • 2、可以自己再次封装下

四、查询语句

  • 1、官方案例地址

  • 2、查询对象中的数据

    first, _ := dao.ReportEntity.WithContext(ctx).
    		Where(gen.Cond(datatypes.JSONQuery("query_param").Extract("gender").Equals("男"))...).First()
    
    SELECT * FROM `report` WHERE JSON_EXTRACT(`query_param`,'$.gender') AND `report`.`deleted_at` IS NULL ORDER BY `report`.`id` LIMIT 1
    

    gorm中正确的使用json数据类型_第2张图片

  • 3、查询数组中是否包括元素

    first, _ := dao.ReportEntity.WithContext(ctx).Where(gen.Cond(datatypes.JSONArrayQuery("query_param").Contains("1"))...).First()
    
     SELECT * FROM `report` WHERE JSON_CONTAINS (`query_param`, JSON_ARRAY('1')) AND `report`.`deleted_at` IS NULL ORDER BY `report`.`id` LIMIT 1
    

    gorm中正确的使用json数据类型_第3张图片

  • 4、查询对象数组中是否包括一个值(官网上没找到合适的方式,只能写原生sql)

    SELECT * from report WHERE query_param->"$[1].age" = 20;
    
    first := model.ReportEntity{}
    w.db.Raw(`SELECT * from report WHERE query_param->"$[1].age" = 20;`).Scan(&first)
    

    gorm中正确的使用json数据类型_第4张图片

你可能感兴趣的:(go,json)