dqjjw04440 2016-03-17 06:37 采纳率: 0%
浏览 92

Postgres在Golang中嵌套JSON结果

I'm using gin and gorp

The 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

The results: enter image description here

Golang

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
}

And returning the results using: c.JSON(200, gin.H{"data": projects})

It works if there's only one project

enter image description here

But if there's more than one project it gives the below error:

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

Any suggestions?

P.S: I'm a newbie in Golang

  • 写回答

2条回答 默认 最新

  • dsznndq4912405 2016-03-17 07:34
    关注

    I made it work using this solution below from this answer

    I don't know how clean of a solution this is but I ended up making my own data type JSONRaw. The DB driver sees it as a []btye but it can still be treated like a json.RawMessage in the Go Code.

    This is a copy paste reimplementation of MarshalJSON and UnmarshalJSON from the encoding/json library.

    //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"`
    }
    

    enter image description here

    But I was wondering if there's a clean way other than this?

    Hope this also help others.

    评论

报告相同问题?

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。