douyi1944 2018-05-08 16: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 18: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
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 CSS实现渐隐虚线边框
  • ¥15 thinkphp6配合social login单点登录问题
  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题