Datatypes:Go 轻松支持数据库JSON类型

GORM 是 Go 语言中最流行的 ORM 之一,它简化了数据库操作,提升了开发效率。然而,在某些情况下,标准的数据类型无法满足复杂业务需求。

例如,**如何将 Go 中的结构体、切片、JSON 等类型映射到数据库字段?**如何方便地进行序列化和反序列化?

为了解决这些问题,GORM 提供了 datatypes (gorm.io/datatypes) 扩展库,旨在简化 Go 语言中复杂数据类型与数据库字段之间的映射和操作。它提供了一系列预定义的数据类型,方便开发者直接使用,而无需自己编写繁琐的转换代码。

datatypes.JSON

datatypes.JSON 允许在数据库中存储 JSON 格式的数据。

定义字段类型 datatypes.JSON :

go 复制代码
import "gorm.io/datatypes"

type User struct {
	ID   int
	Name string
	Conf datatypes.JSON // 对应数据库JSON类型
}

func (u User) TableName() string {
	return "test_json_user"
}

插入 JSON 数据:

go 复制代码
	user := User{
		Name: "Alice",
		Conf: datatypes.JSON(`{"theme": "dark", "lang": "en"}`),
	}
	db.Create(&user)
	// INSERT INTO `test_json_user` (`name`,`conf`) VALUES ('Alice',CAST('{"theme": "dark", "lang": "en"}' AS JSON))

检查 JSON 键对应的值是否等于指定值:

查找 conf 字段中 theme 键的值是否为 "dark"。

go 复制代码
	var result User
	db.Where(datatypes.JSONQuery("conf").Equals("dark", "theme")).Find(&result)
	// SELECT * FROM `test_json_user` WHERE JSON_EXTRACT(`conf`,'$.theme') = 'dark'

查询 JSON 数据:

可以使用 json.Unmarshal 解析 JSON 结构。

go 复制代码
type Conf struct {
	Theme string `json:"theme"`
	Lang  string `json:"lang"`
}

	var result User
	db.Where("name = ?", "Alice").Find(&result)

	var conf Conf
	json.Unmarshal(result.Conf, &conf)
	fmt.Printf("%+v\n", conf)
	// {Theme:dark Lang:en}

datatypes.JSONTypeT

与使用 datatypes.JSON 需手动解析数据到结构体不同,使用 datatypes.JSONTypeT,查询时它可以自动将 JSON 数据映射到 Go 结构体。

定义字段类型 datatypes.JSONTypeT

go 复制代码
type User struct {
	ID   int
	Name string
	Conf datatypes.JSONType[Conf]// 对应数据库JSON类型
}

type Conf struct {
	Theme string `json:"theme"`
	Lang  string `json:"lang"`
}

插入 JSON 数据:

go 复制代码
	conf := Conf{Theme: "dark", Lang: "en"}

	user := User{
		Name: "Alice",
		Conf: datatypes.NewJSONType(conf),
	}
	db.Create(&user)

查询 JSON 数据:

查询时自动将 JSON 数据映射到 Go 结构体。使用 result.Conf.Data() 可以直接访问 JSON 数据中的字段。

go 复制代码
	var result User
	db.Where("name = ?", "Alice").Find(&result)
	fmt.Printf("%+v\n", result.Conf.Data()) // {Theme:dark Lang:en}
	fmt.Println(result.Conf.Data().Theme)   // dark
	fmt.Println(result.Conf.Data().Lang)    // en

datatypes.JSONSliceT

datatypes.JSONSlice 可以方便地存储 JSON 数组。查询时自动解析 JSON 数组。

定义字段类型 datatypes.JSONSliceT

go 复制代码
type User struct {
	ID   int
	Name string
	Conf datatypes.JSONSlice[Conf] // 对应数据库JSON类型
}

type Conf struct {
	Theme string `json:"theme"`
	Lang  string `json:"lang"`
}

插入 JSON 数据:

go 复制代码
	conf := []Conf{
		{Theme: "dark", Lang: "en"},
		{Theme: "light", Lang: "zh"},
	}

	user := User{
		Name: "Alice",
		Conf: datatypes.NewJSONSlice(conf),
	}
	db.Create(&user)
	// INSERT INTO `test_json_user` (`name`,`conf`) VALUES ('Alice',CAST('[{"theme":"dark","lang":"en"},{"theme":"light","lang":"zh"}]' AS JSON))
    
/*	另一个例子储存int数组
	type User struct {
		ID   int
		Name string
		Conf datatypes.JSONSlice[int] // 对应数据库JSON类型
	}

	conf := []int{1, 2, 3, 4}

	user := User{
		Name: "Alice",
		Conf: datatypes.NewJSONSlice(conf),
	}
	db.Create(&user)*/    

查询 JSON 数据:

go 复制代码
	var result User
	db.Where("name = ?", "Alice").Find(&result)
	fmt.Printf("%+v\n", result.Conf)  // [{Theme:dark Lang:en} {Theme:light Lang:zh}]
	fmt.Println(result.Conf[0].Theme) // dark
	fmt.Println(result.Conf[0].Lang)  // en

通过这些示例,我们可以看到 gorm.io/datatypes 的强大之处:它简化了复杂数据类型的处理,让开发者可以更专注于业务逻辑。了解更多数据类型和使用方法请阅读官方文档。


References

github.com/go-gorm/dat...

相关推荐
长大19882 小时前
新手必踩 Redis 10 个低级坑:过期时间、KEYS 命令、持久化误区
后端
Csvn3 小时前
Python 两大经典坑点 —— 可变默认参数 & 闭包延迟绑定
后端·python
Csvn3 小时前
定时任务 — Crontab 从入门到生产实战
后端
ServBay4 小时前
Laravel Herd MCP 的替代,多语言与跨平台的 AI 本地开发选择
后端·ai编程·mcp
GoGeekBaird5 小时前
Prompt、Context、Harness 工程全景图
后端
SimonKing5 小时前
艹,维护AI写的代码,我心态崩了......
java·后端·程序员
AskHarries5 小时前
MCP 基础:Server、Tool、Resource 和 Prompt
后端·程序员