卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章34017本站已运行391

为什么 JSONB 以字符串形式返回?

为什么 jsonb 以字符串形式返回?

问题内容

我已经启动了一个“instagram 克隆”后端来尝试学习有关 golang 的知识,但我遇到了一个不知道如何解决的问题。

我用 fiber 构建了一个简单的 api,可以获取一些帖子:

package server

import (
    "fmt"
    "instagram/internal/psql"
    queries "instagram/internal/sql"
    "net/http"

    "github.com/gofiber/fiber/v2"
)

type like struct {
    username string
    name     string
    picture  string
}

type post struct {
    id          string `json:"id"`
    description string `json:"description"`
    media       string `json:"media"`
    type        string `json:"type"`
    likes       string `json:"likes"`
    user_id     string `json:"user_id"`
    created_at  string `json:"created_at"`
    updated_at  string `json:"updated_at"`
}

func listposts(c *fiber.ctx) error {
    rows, err := psql.db().query(queries.getallposts)

    if err != nil {
        c.sendstatus(400)
        return nil
    }

    defer rows.close()
    var data []post

    for rows.next() {
        var post post
        err := rows.scan(&post.id, &post.description, &post.media, &post.type, &post.created_at, &post.updated_at, &post.likes, &post.user_id)
        if err != nil {
            fmt.print(err)
            c.sendstatus(400)
            return nil
        }

        data = append(data, post)
    }

    return c.status(http.statusok).json(data)
}

问题是 likes 属性作为字符串返回:

[
    {
        "id": "...",
        "description": "...",
        "media": "...",
        "type": "...",
        "likes": "[]",
        "user_id": "...",
        "created_at": "...",
        "updated_at": "..."
    }
]

我尝试了一些东西,比如使用 json.marshal(data),我还写了 like 结构,但我无法使其工作,因为当我将 likes 的类型从 string 更改为 []like 时调用扫描时出现以下消息


sql: scan error on column index 6, name "likes": unsupported scan, storing driver.value type []uint8 into type *[]server.likesql: scan error on column index 6, name "likes": unsupported scan, storing driver.value type []uint8 into type *[]server.like

我正在使用 postgresql 数据库,并且我第一次尝试使用 jsonb 列,因此 likes 在数据库中是 jsonb 列。

我理想的有效负载是这样的:

[
    {
        "id": "...",
        "description": "...",
        "media": "...",
        "type": "...",
        "likes": [],
        "user_id": "...",
        "created_at": "...",
        "updated_at": "..."
    }
]

请注意,likes 现在是一个数组而不是字符串。那么有人知道如何解决这个问题吗?


正确答案


您很可能需要实现 sql.driver 的接口来“知道”如何扫描到您的结构,可能类似于

type Like struct {
    Username string
    Name     string
    picture  string
}

type Likes []Like

func (l Likes) Value() (driver.Value, error) {
    return json.Marshal(l)
}

// Make the Likes implement the sql.Scanner interface.
func (l *Likes) Scan(value interface{}) error {
    b, ok := value.([]byte)
    if !ok {
        return errors.New("type assertion to []byte failed")
    }

    return json.Unmarshal(b, &l)
}
卓越飞翔博客
上一篇: 是否存在将程序的输出作为流逐行读取的概念?
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏