1 回答

TA贡献1802条经验 获得超4个赞
以防万一您不知道,jsonb[]这是一个PostgreSQL 数组类型,其元素类型为jsonb. 它不是“json 数组”类型。
如果要将 JSON 数据存储在列中,无论您希望该数据包含标量、对象还是数组JSON 值,都应使用json/类型。jsonb
因此,除非您选择 PostgreSQL 数组类型时考虑了一些特定的用例,否则最好将列的类型从更改jsonb[]为jsonb.
如果您不能或不想更改列类型,那么您仍然可以在 SELECT 查询中将 PostgreSQL 数组转换为 JSON 数组,然后,在您的自定义 Gosql.Scanner实现中,用于json.Unmarshal解码数据库数据.
SELECT to_jsonb(advance_payment) FROM booking_settings WHERE hotel_id = $1
-- or
SELECT array_to_json(advance_payment)::jsonb FROM booking_settings WHERE hotel_id = $1
type advanceAndRoomPaymentList []advanceAndRoomPayment
func (ls *advanceAndRoomPaymentList) Scan(src any) error {
var data []byte
switch v := src.(type) {
case string:
data = []byte(v)
case []byte:
data = v
}
return json.Unmarshal(data, ls)
}
如果您有许多查询引用 PostgreSQL 数组列并且您不想更新每个查询以进行转换,您可以自己解析 PostgreSQL 数组然后解组各个元素,或者您可以将这项工作委托给某些人第 3 方实施。
这是一个未经测试的示例,使用pq.GenericArray:
// I haven't tested the following but I'd assume it ought to work,
// if not, then perhaps maybe small tweaks are needed here and there...
type advanceAndRoomPaymentList []advanceAndRoomPayment
func (ls *advanceAndRoomPaymentList) Scan(src any) error {
return pq.GenericArray{ls}.Scan(src)
}
// implement Scanner for the element type of the slice
func (a *advanceAndRoomPayment) Scan(src any) error {
var data []byte
switch v := src.(type) {
case string:
data = []byte(v)
case []byte:
data = v
}
return json.Unmarshal(data, a)
}
如果您想自己解析 PostgreSQL 数组,那么您需要了解用于表示此类数组的语法。您可以在此处找到相关文档:
数组值的外部文本表示由根据数组元素类型的 I/O 转换规则解释的项以及指示数组结构的装饰组成。装饰由围绕数组值的大括号({ 和 })加上相邻项之间的定界符组成。分隔符通常是逗号 (,),但也可以是其他字符:它由数组元素类型的 typdelim 设置决定。在 PostgreSQL 发行版提供的标准数据类型中,除了 type box 使用分号(;)外,都使用逗号。
因此,例如,如果您有包含一个 json 对象、一个 json 数组、一个 json 字符串和一个 json 布尔的 pg 数组,并且您选择了它,那么将传递给sql.Scanner实现的数组表示将看起来像:
{"{\"foo\": \"bar\"}","[\"foo\", \"bar\"]","\"foo bar\"",true}
- 1 回答
- 0 关注
- 288 浏览
添加回答
举报