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...

相关推荐
To_OC6 小时前
从一头雾水到跑通全流程:我用一个周末啃透了JWT登录鉴权
前端·后端·http
前端兰博7 小时前
05-Redis
redis·后端
databook7 小时前
从手动检查到自动监控:一个数据质量工作流的实现
后端·python·数据分析
【JAVA】玩家8 小时前
Spring核心原理全解析:从零到生产实战
java·后端·spring
东风破_8 小时前
从 Neo4j 到 GraphRAG:用 Text-to-Cypher 构建图检索 RAG
人工智能·后端
llqbzllll10 小时前
Spring AI 工具调用不是反射一下就结束:用 2.0.1 跑通失败恢复与调用上限
人工智能·后端
狼爷10 小时前
Rust/Go/Java/Python/PHP 大比拼:负载下后端框架到底差多少?
java·后端·编程语言
mantou13211 小时前
我给 AI Agent 做了个「油猴」:让 Claude Code / Codex 直接用你已登录的浏览器
前端·javascript·后端
程序员老赵11 小时前
Docker 部署 DeepSeek Harness:轻松搭建局域网里的 AI Agent 平台
后端·ai编程·deepseek
YIAN11 小时前
实战|用 DeepSeek + SQLite 从零搭建轻量 Text2SQL 查询助手
后端·sqlite·deepseek