package utils import ( "database/sql" jsoniter "github.com/json-iterator/go" ) // UnmarshalSQLRows unmarshals sql rows to json // // This function provides a way to unmarshal arbitrary sql rows // to json. func UnmarshalSQLRows(rows *sql.Rows) ([]byte, error) { columnTypes, err := rows.ColumnTypes() if err != nil { return nil, err } count := len(columnTypes) finalRows := []interface{}{} for rows.Next() { scanArgs := make([]interface{}, count) for i, v := range columnTypes { switch v.DatabaseTypeName() { case "VARCHAR", "TEXT", "UUID", "TIMESTAMP": scanArgs[i] = new(sql.NullString) case "BOOL": scanArgs[i] = new(sql.NullBool) case "INT4": scanArgs[i] = new(sql.NullInt64) default: scanArgs[i] = new(sql.NullString) } } err := rows.Scan(scanArgs...) if err != nil { return nil, err } masterData := map[string]interface{}{} for i, v := range columnTypes { if z, ok := (scanArgs[i]).(*sql.NullBool); ok { masterData[v.Name()] = z.Bool continue } if z, ok := (scanArgs[i]).(*sql.NullString); ok { masterData[v.Name()] = z.String continue } if z, ok := (scanArgs[i]).(*sql.NullInt64); ok { masterData[v.Name()] = z.Int64 continue } if z, ok := (scanArgs[i]).(*sql.NullFloat64); ok { masterData[v.Name()] = z.Float64 continue } if z, ok := (scanArgs[i]).(*sql.NullInt32); ok { masterData[v.Name()] = z.Int32 continue } masterData[v.Name()] = scanArgs[i] } finalRows = append(finalRows, masterData) } return jsoniter.Marshal(finalRows) }