postgresql - 从 postgresql 获得的对象的 Unmarshal Json Array
问题描述
我在 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
前任:
Insert into Business(id_category, name, owner, coordinates, reason)
values
(1,'MyName','Owner', [{"latitude": 12.1268142, "longitude": -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类型[] uint8存储到类型*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.
正如您从文档中看到的那样Scanner
,要满足接口,需要该方法
Scan(src interface{}) error
但是您的*Coordinates
类型实现了不同的方法
Scan(value []interface{}) error
类型interface{}
和[]interface{}
是两个非常不同的东西。
2.
Scanner 接口必须在要作为参数传递给的字段类型上实现rows.Scan
。也就是说,您已经实现了您的Scan
方法,*Coordinates
但 Location 字段的类型是[]Coordinates
.
同样,类型*Coordinates
和[]Coordinates
是两个非常不同的东西。
所以解决方案是正确实现接口并在正确的类型上。
请注意,由于 Go 不允许向未命名类型添加方法,并且[]Coordinates
是未命名类型,因此您需要声明一个新类型,然后使用它来代替[]Coordinates
.
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 对象存储到数据库中,并将Location
类型从CoordinatesSlice
to更改为Coordinates
并相应地将Scanner
实现从*CoordinatesSlice
to移动*Coordinates
。
推荐阅读
- reactjs - 无法更新未安装组件的状态/ useEffect 最终返回 null
- angular - 如何通过重新输入原始值使 Angular 表单字段“干净”?
- office-js - 为什么值 any[][]
- javascript - 如何在不更改时间的情况下将日期时间与时区连接起来
- dm-script - 如何在 GMS3 中创建滑块
- python - 美汤如何正确提取ul中的li元素?
- ios - iPA 构建失败并出现异常 - 为 QA 测试/ AdHod 准备构建时出现 NonZeroExcitException
- laravel-datatables - 无法对 laravel 数据表上的添加列进行排序
- amazon-web-services - 一次调用在无服务器中获取两个 Step Function 执行 [AWS]
- spring-boot - 如何使用 Spring Cloud Dataflow 将 Twitter 流数据持久化到 Postgres 数据库?