douyi1944 2018-05-08 08:36
浏览 58
已采纳

如何将pgx.Rows从Query()转换为json数组?

I'm using github.com/jackc/pgx for work with postgreSQL. Noq I want to convert pgx.Rows from Query() to json array. I tried func for *sql.Rows, but it doesn't work for *pgx.Rows

func PgSqlRowsToJson(rows *pgx.Rows) []byte {
   fieldDescriptions := rows.FieldDescriptions()
   var columns []string
   for _, col := range fieldDescriptions {
    columns = append(columns, col.Name)
   }

   count := len(columns)
   tableData := make([]map[string]interface{}, 0)
   values := make([]interface{}, count)
   valuePtrs := make([]interface{}, count)
   for rows.Next() {
    for i := 0; i < count; i++ {
        valuePtrs[i] = &values[i]
    }
    rows.Scan(valuePtrs...)
    entry := make(map[string]interface{})
    for i, col := range columns {
        var v interface{}
        val := values[i]
        b, ok := val.([]byte)
        if ok {
            v = string(b)
        } else {
            v = val
        }
        entry[col] = v
    }
    tableData = append(tableData, entry)
   }
   jsonData, _ := json.Marshal(tableData)

   return jsonData
}

The problem is that Scan() doesn't work with interface{} and it works with explicitly defined types only. Can you help me how to fix it?

展开全部

  • 写回答

1条回答 默认 最新

  • duanjianhe1388 2018-05-08 10:49
    关注

    You can use the pgx.FieldDescription's Type method to retrieve a column's expected type. Passing that to reflect.New you can then allocate a pointer to a value of that type, and with these newly allocated values you can then make a slice of non-nil interface{}s whose underlying values have the expected type.

    For example:

    func PgSqlRowsToJson(rows *pgx.Rows) []byte {
        fieldDescriptions := rows.FieldDescriptions()
        var columns []string
        for _, col := range fieldDescriptions {
            columns = append(columns, col.Name)
        }
    
        count := len(columns)
        tableData := make([]map[string]interface{}, 0)
    
        valuePtrs := make([]interface{}, count)
        for rows.Next() {
            for i := 0; i < count; i++ {
                valuePtrs[i] = reflect.New(fieldDescriptions[i].Type()).Interface() // allocate pointer to type
            }
            rows.Scan(valuePtrs...)
    
            entry := make(map[string]interface{})
            for i, col := range columns {
                var v interface{}
                val := reflect.ValueOf(valuePtrs[i]).Elem().Interface() // dereference pointer
                b, ok := val.([]byte)
                if ok {
                    v = string(b)
                } else {
                    v = val
                }
                entry[col] = v
            }
            tableData = append(tableData, entry)
        }
        jsonData, _ := json.Marshal(tableData)
    
        return jsonData
    }
    

    展开全部

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部