猿问

如何将 jsonb 对象从 Postgresql 扫描到 golang 结构

首先,我尝试了过去 stackoverflow 答案中的解决方案,这些答案的问题与我的问题相关,但没有任何效果,这就是为什么我将其作为一个单独的问题提出。


我在 golang 中有两个结构


type otherPayments struct {

    DebitTo     int    `json:"debit_To" binding:"required"`

    CreditFrom  int    `json:"credit_from" binding:"required"`

    OverallType string `json:"overall_type" binding:"required"`

}


type advanceAndRoomPayment struct {

    PmID        int    `json:"pm_id" binding:"required"`        //Payment method id

    PmName      string `json:"pm_name" binding:"required"`      //Payment method name

    DebitTo     int    `json:"debit_To" binding:"required"`     //The ledger to debit from

    CreditFrom  int    `json:"credit_from" binding:"required"`  //The ledger to credit from

    OverallType string `json:"overall_type" binding:"required"` //Overall transaction type

}

我的postgresql 表中有5SQL 列booking_settings

  • initial列,类型 = otherPaymentsJSONB

  • cancellation, 输入 = otherPayments,JSONB

  • updation, 输入 = otherPayments,JSONB

  • advance_payment输入 = advanceAndRoomPayment,JSONB []

  • room_payment, 输入 = advanceAndRoomPayment,JSONB []

查询SELECT如下

SELECT initial, cancellation, updation advance_payment, room_payment FROM booking_settings WHERE hotel_id = $1

我使用的 sql 包是https://jmoiron.github.io/sqlx/

我正在尝试将上面的列扫描到它们适当的结构变量中,到目前为止我只能设法扫描initial, cancellation and updation而不是JSONB [] advance_payment and room_payment

非常感谢任何帮助,谢谢



手掌心
浏览 237回答 1
1回答

慕虎7371278

以防万一您不知道,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-- orSELECT array_to_json(advance_payment)::jsonb FROM booking_settings WHERE hotel_id = $1type advanceAndRoomPaymentList []advanceAndRoomPaymentfunc (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 []advanceAndRoomPaymentfunc (ls *advanceAndRoomPaymentList) Scan(src any) error {    return pq.GenericArray{ls}.Scan(src)}// implement Scanner for the element type of the slicefunc (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}
随时随地看视频慕课网APP

相关分类

Go
我要回答