Golang如何将列表整体而非逐行序列化为正确JSON格式?
Golang如何将列表整体而非逐行序列化为正确JSON格式? 我有这段代码可以将单行数据正确序列化输出:
var rows *sql.Rows
rows, err = db.Query(query)
cols, _ := rows.Columns()
colnames, _ := rows.Columns()
vals := make([]interface{}, len(cols))
for i, _ := range cols { //bytes to string
vals[i] = &cols[i]
}
mymap := make(map[string]interface{})
for i, v := range vals { //adding column names
mymap[colnames[i]] = v
}
for rows.Next() {
err = rows.Scan(vals...)
json, _ := json.Marshal(mymap)
fmt.Fprintf(w,"%s\n",json)
}
输出结果会是这样的:
{“ID”:“1”,“NAME”:“John Doe”}
{“ID”:“2”,“NAME”:“Jane Doe”}
但我需要的是用逗号分隔的完整数据块:
[{“ID”:“1”,“NAME”:“John Doe”},
{“ID”:“2”,“NAME”:“Jane Doe”}]
作为一个完全的新手,我想应该序列化整个列表而不是每一行数据:
for rows.Next() {
err = rows.Scan(vals...)
append (list, vals) //save to a list
}
json, _ := json.Marshal(list) //marshal the list instead of each row
fmt.Fprintf(w,"%s\n",json)
我该怎么做?
更多关于Golang如何将列表整体而非逐行序列化为正确JSON格式?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我从StackOverflow找到了解决方案
只需创建一个切片来存储你的映射,然后进行序列化。
var mySlice = make([]map[string]interface{}, 0)
for rows.Next() {
err = rows.Scan(vals…)
mySlice = append(mySlice, mymap)
}
json, _ := json.Marshal(mySlice)
fmt.Printf("%s\n", json)
你在对切片值的指针进行复杂操作,并且总是扫描到同一个切片(vals,包含指向cols的指针)中,覆盖了原有值。我理解你试图基于表结构实现完全动态的功能,但初始代码中多层间接引用甚至让我都有些困惑。
func main() {
fmt.Println("hello world")
}
calmh:
我理解你试图基于表结构实现完全动态的功能,但初始代码中的间接层级甚至让我都感到有些皱眉。
我完全是Golang的新手,正在通过实践学习。
主要目标是在不了解结构体的情况下从SQL获取数据,并将其解析为JSON。我开始觉得这对于新手来说要么不可能,要么太难了。
我认为这个版本更容易理解
var arr []string
for rows.Next() {
err = rows.Scan(vals...)
m := make(map[string]interface{})
for i, v := range vals {
m[colnames[i]] = v
}
str, _ := json.Marshal(m)
arr = append(arr, string(str))
}
json, _ := json.Marshal(arr)
fmt.Println(string(json))
var rows *sql.Rows
rows, err = db.Query(query)
cols, _ := rows.Columns()
colnames, _ := rows.Columns()
vals := make([]interface{}, len(cols))
var arr []map[string]interface{}
for rows.Next() {
err = rows.Scan(vals...)
m := make(map[string]interface{})
for i, v := range vals {
m[colnames[i]] = v
}
str, _ := json.Marshal(m)
fmt.Println(string(str))
arr = append(arr, m)
}
返回的结果只有一个"null"。请问我哪里做错了?
var mySlice = make([]map[string]interface{}, 0)
for rows.Next() {
err = rows.Scan(vals…)
mySlice = append(mySlice, mymap)
}
json, _ := json.Marshal(mySlice)
fmt.Printf("%s\n", json)
这输出了正确的JSON,但是相同的值ID 1被重复了:
[{“ID”:“1”,“NAME”:“John Doe”},
{“ID”:“1”,“NAME”:“John Doe”}]
应该是不同的值:
[{“ID”:“1”,“NAME”:“John Doe”},
{“ID”:“2”,“NAME”:“Jane Doe”}]
有谁知道哪里出问题了吗?
var arr []map[string]interface{}
for rows.Next() {
err = rows.Scan(vals...)
m := make(map[string]interface{})
for i, v := range vals {
m[colnames[i]] = v
}
str, _ := json.Marshal(m)
fmt.Println(string(str))
arr = append(arr, m)
}
json, _ := json.Marshal(arr)
fmt.Println(string(json))
我没有编写测试代码,所以很好奇为什么它总是返回相同的数据。 在下面的代码中,我认为每次调用都会创建一个映射
实际上,映射中的数据正确显示,然后映射(新指针)被添加到切片中,因此不可能重写它。但是,当写入切片时,只显示最后一个
对此有什么提示吗? 问候
var rows *sql.Rows
rows, err = db.Query(query)
cols, _ := rows.Columns()
colnames, _ := rows.Columns()
vals := make([]interface{}, len(cols))
for i, _ := range cols { //bytes to string
vals[i] = &cols[i]
}
mymap := make(map[string]interface{})
for i, v := range vals { //adding column names
mymap[colnames[i]] = v
}
for rows.Next() {
err = rows.Scan(vals...)
json, _ := json.Marshal(mymap)
fmt.Fprintf(w,"%s\n",json)
}
这段代码能生成正确的JSON,但会重复相同的值ID 1:
[{“ID”:“1”,“NAME”:“John Doe”}, {“ID”:“1”,“NAME”:“John Doe”}]
实际发生的情况是:
第一行:{“ID”:“1”,“NAME”: "John } 第二行:{“ID”:“2”,“NAME”: “Jane Doe”}, {“ID”:“2”,“NAME”: “Jane Doe”} 第三行:{“ID”:“3”,“NAME”: “Donald Duck”},{“ID”:“3”,“NAME”: “Donald Duck”},{“ID”:“3”,“NAME”: “Donald Duck”}
rows.Scan能获取正确的值,但它会追加并替换所有之前的值。
有没有办法在遍历行时不替换之前的值?
这是一个常见的数据序列化问题。你需要将所有行数据收集到一个切片中,然后对整个切片进行JSON序列化。以下是正确的实现方式:
var rows *sql.Rows
rows, err = db.Query(query)
cols, _ := rows.Columns()
// 创建结果切片
var results []map[string]interface{}
for rows.Next() {
// 为每一行创建新的值切片
vals := make([]interface{}, len(cols))
for i := range cols {
vals[i] = new(interface{})
}
err = rows.Scan(vals...)
if err != nil {
// 处理错误
continue
}
// 创建当前行的映射
rowMap := make(map[string]interface{})
for i, col := range cols {
// 解引用interface{}指针获取实际值
val := *(vals[i].(*interface{}))
// 处理不同类型的数据
switch v := val.(type) {
case []byte:
rowMap[col] = string(v)
default:
rowMap[col] = v
}
}
// 将行数据添加到结果切片
results = append(results, rowMap)
}
// 序列化整个结果集
jsonData, err := json.Marshal(results)
if err != nil {
// 处理序列化错误
fmt.Fprintf(w, "Error: %s", err)
return
}
fmt.Fprintf(w, "%s", jsonData)
这个实现会输出你期望的JSON数组格式:
[{"ID":"1","NAME":"John Doe"},{"ID":"2","NAME":"Jane Doe"}]
关键点:
- 使用
[]map[string]interface{}来存储所有行数据 - 在循环中为每一行创建新的
vals切片,避免数据覆盖 - 使用类型断言正确处理
[]byte类型的数据 - 最后对整个结果切片进行序列化
如果你想要更简洁的版本,也可以这样实现:
var results []map[string]string
cols, _ := rows.Columns()
for rows.Next() {
vals := make([]interface{}, len(cols))
for i := range cols {
vals[i] = new(sql.NullString)
}
rows.Scan(vals...)
rowMap := make(map[string]string)
for i, col := range cols {
if ns, ok := vals[i].(*sql.NullString); ok && ns.Valid {
rowMap[col] = ns.String
}
}
results = append(results, rowMap)
}
jsonData, _ := json.Marshal(results)
fmt.Fprintf(w, "%s", jsonData)


