解组从postgresql获取的对象的Json数组

解组从postgresql获取的对象的Json数组,postgresql,go,Postgresql,Go,我在Postgres中有一个表,它是Jsonb Create Table Business( id serial not null primary key, id_category integer not null, name varchar(50) not null, owner varchar(200) not null, coordinates jsonb not null, reason varchar(300) not null,

我在Postgres中有一个表,它是Jsonb

Create Table Business(
    id serial not null primary key,
    id_category integer not null,
    name varchar(50) not null,
    owner varchar(200) not null,
    coordinates jsonb not null,
    reason varchar(300) not null,
    foreign key(id_category) references Category(id)
);
如您所见,我将坐标存储为jsonb

例:

插入业务(id\u类别、名称、所有者、坐标、原因)
价值观
(1,'MyName','Owner',[{“纬度”:12.1268142,“经度”:-86.2754}','Description')
我提取数据并分配数据的方式如下

type Business struct {
    ID int `json:"id,omitempty"`
    Name string `json:"name,omitempty"`
    Owner string `json:"owner,omitempty"`
    Category string `json:"category,omitempty"`
    Departments []string `json:"departments,omitempty"`
    Location []Coordinates `json:"location,omitempty"`
    Reason string `json:"reason,omitempty"`
}

type Coordinates struct {
    Latitude float64 `json:"latitude,omitempty"`
    Longitude float64 `json:"longitude,omitempty"`
}

func (a Coordinates) Value() (driver.Value, error) {
    return json.Marshal(a)
}

func (a *Coordinates) Scan(value []interface{}) error {
    b, ok := value.([]byte)
    if !ok {
        return errors.New("type assertion to []byte failed")
    }
    return json.Unmarshal(b, &a)
}
然而,我一直收到这个消息

sql:列索引3上的扫描错误,名称为“坐标”:不支持 扫描并将driver.Value type[]uint8存储到type*models.Coordinates中

我用来提取信息的控制器是这个

func (b *BusinessRepoImpl) Select() ([]models.Business, error) {
    business_list := make([]models.Business, 0)
    rows, err := b.Db.Query("SELECT business.id, business.name, business.owner, business.coordinates, business.reason_froggy, category.category FROM business INNER JOIN category on category.id = business.id_category group by business.id, business.name, business.owner, business.coordinates, business.reason_froggy, category.category")
    if err != nil {
        return business_list, err
    }
    for rows.Next() {
        business := models.Business{}
        err := rows.Scan(&business.ID, &business.Name, &business.Owner, &business.Location, &business.Reason, &business.Category)
        if err !=  nil {
            break
        }
        business_list = append(business_list, business)
    }
    err = rows.Err()
    if err != nil {
        return business_list, err
    }
    return business_list, nil
}
谁能告诉我如何解决这个问题?检索对象的json数组并将其分配给Business内部的坐标字段。

1。

正如您从文档中看到的,要满足该接口,需要使用该方法

Scan(src interface{}) error
但是您的
*坐标
类型实现了一种不同的方法

Scan(value []interface{}) error
类型
interface{}
[]interface{}
是两种截然不同的东西

2.

Scanner接口必须在要作为参数传递给的字段类型上实现。也就是说,您已经在
*坐标
上实现了
扫描
方法,但是位置字段的类型是
[]坐标

type CoordinatesSlice []Coordinates

func (s *CoordinatesSlice) Scan(src interface{}) error {
    switch v := src.(type) {
    case []byte:
        return json.Unmarshal(v, s)
    case string:
        return json.Unmarshal([]byte(v), s)
    }
    return errors.New("type assertion failed")
}

// ...

type Business struct {
    // ...
    Location CoordinatesSlice `json:"location,omitempty"`
    // ...
}
同样,类型
*坐标
[]坐标
是两个非常不同的东西


因此,解决方案是在适当的类型上正确地实现接口

请注意,由于Go不允许向未命名类型添加方法,并且
[]坐标
是未命名类型,因此需要声明一个新类型,然后使用该类型代替
[]坐标

type CoordinatesSlice []Coordinates

func (s *CoordinatesSlice) Scan(src interface{}) error {
    switch v := src.(type) {
    case []byte:
        return json.Unmarshal(v, s)
    case string:
        return json.Unmarshal([]byte(v), s)
    }
    return errors.New("type assertion failed")
}

// ...

type Business struct {
    // ...
    Location CoordinatesSlice `json:"location,omitempty"`
    // ...
}

注意


如果业务位置始终只有一对坐标作为jsonb对象存储在db中,并将
位置
类型从
坐标板
更改为
坐标
,并相应地将
扫描仪
实现从
*坐标板
移动到
*坐标
I要知道这个解决方案实际上是未优化的,但这是唯一可行的方法

type CoordinatesSlice []Coordinates

func (s *CoordinatesSlice) Scan(src interface{}) error {
    switch v := src.(type) {
    case []byte:
        return json.Unmarshal(v, s)
    case string:
        return json.Unmarshal([]byte(v), s)
    }
    return errors.New("type assertion failed")
}

// ...

type Business struct {
    // ...
    Location CoordinatesSlice `json:"location,omitempty"`
    // ...
}
基本上,我必须获得json,然后对Location属性进行解组

var location string = ""

if err := json.Unmarshal([]byte(location), &business.Location); err != nil { panic(err) }

这就是我使用的所有代码,或者你需要更具体的东西?