1

我正在使用杜松子酒gorp

SQL:

SELECT p.project_id, p.name, 

COALESCE(NULLIF(json_agg(a.*)::TEXT, '[null]'), '[]')::JSON AS apps 

FROM project p LEFT JOIN app a USING (project_id) 

WHERE p.user_id=19 

GROUP BY p.project_id, p.name ORDER BY project_id

结果: 在此处输入图像描述

戈朗

type Project struct {
    ID        int64           `db:"project_id, primarykey, autoincrement" json:"id"`
    UserID    int64           `db:"user_id" json:"user_id"`
    Name      string          `db:"name" json:"name"`
    Status    int             `db:"status" json:"status"`
    UpdatedAt int64           `db:"updated_at" json:"updated_at"`
    CreatedAt int64           `db:"created_at" json:"created_at"`
    Apps      json.RawMessage `json:"apps"`
}


func GetProjects(userID int64, page string) []Project {
    var projects []Project

    var err error
    _, err = db.GetDB().Select(&projects, "SELECT p.project_id, p.name, COALESCE(NULLIF(json_agg(a.*)::TEXT, '[null]'), '[]')::JSON AS apps FROM project p LEFT JOIN app a USING (project_id) WHERE p.user_id=$1 GROUP BY p.project_id, p.name ORDER BY project_id LIMIT 10 OFFSET $2", userID, page)
    fmt.Println("err", err)

    return projects
}

并使用以下方法返回结果:c.JSON(200, gin.H{"data": projects})

如果只有一个项目,它可以工作

在此处输入图像描述

但如果有多个项目,则会出现以下错误:

错误:json: error calling MarshalJSON for type json.RawMessage: invalid character '"' after top-level value

有什么建议么?

PS:我是Golang的新手

4

2 回答 2

2

您可以使用此站点http://json2struct.mervine.net/根据结果获取正确的结构。只需复制选择结果,并生成您体面的结构

或者您可以生成具有 Project struct 数组的新类型:

type Projects []Project
于 2016-03-17T09:46:50.483 回答
0

我从这个答案中使用下面的这个解决方案使它工作

我不知道这是一个多么干净的解决方案,但我最终制作了自己的数据类型JSONRaw。DB 驱动程序将其视为 a ,但在 Go 代码中[]btye仍可将其视为 a 。json.RawMessage

这是对 encoding/json 库MarshalJSON的复制粘贴重新实现。UnmarshalJSON

//JSONRaw ...
type JSONRaw json.RawMessage

//Value ...
func (j JSONRaw) Value() (driver.Value, error) {
    byteArr := []byte(j)

    return driver.Value(byteArr), nil
}

//Scan ...
func (j *JSONRaw) Scan(src interface{}) error {
    asBytes, ok := src.([]byte)
    if !ok {
        return error(errors.New("Scan source was not []bytes"))
    }
    err := json.Unmarshal(asBytes, &j)
    if err != nil {
        return error(errors.New("Scan could not unmarshal to []string"))
    }

    return nil
}

//MarshalJSON ...
func (j *JSONRaw) MarshalJSON() ([]byte, error) {
    return *j, nil
}

//UnmarshalJSON ...
func (j *JSONRaw) UnmarshalJSON(data []byte) error {
    if j == nil {
        return errors.New("json.RawMessage: UnmarshalJSON on nil pointer")
    }
    *j = append((*j)[0:0], data...)
    return nil
}

//Project ....
type Project struct {
    ID        int64   `db:"project_id, primarykey, autoincrement" json:"id"`
    UserID    int64   `db:"user_id" json:"user_id"`
    Name      string  `db:"name" json:"name"`
    Status    int     `db:"status" json:"status"`
    UpdatedAt int64   `db:"updated_at" json:"updated_at"`
    CreatedAt int64   `db:"created_at" json:"created_at"`
    Apps      JSONRaw `json:"apps"`
}

在此处输入图像描述

但我想知道除此之外是否还有其他干净的方法?

希望这也对其他人有所帮助。

于 2016-03-17T07:34:03.970 回答