Golang中如何实现map和json的字段自动排序

Golang中如何实现map和json的字段自动排序 我遇到了一个问题。 我从数据库中获取行数据并将其写入映射接口。 然后将其转换为JSON并发送给客户端。

我需要保持数据库中指定的字段顺序。

以下是一段代码片段:

rows, _ := db.Query("SELECT * FROM table")
cols, _ := rows.Columns()

defer rows.Close()

d:= make([]map[string]interface{}, 0)
for rows.Next() {
	columns := make([]interface{}, len(cols))
	columnPointers := make([]interface{}, len(cols))
	for i, _ := range columns {
		columnPointers[i] = &columns[i]
	}

	rows.Scan(columnPointers...)

	m := make(map[string]interface{})
	for i, colName := range cols {
		val := columnPointers[i].(*interface{})
		m[colName] = *val
	}

	d = append(d, m)
}
fmt.Println(d[100])
jsData, _ := json.Marshal(d)
w.Header().Set("Content-Type", "application/json")
w.Write(jsData)

更多关于Golang中如何实现map和json的字段自动排序的实战教程也可以访问 https://www.itying.com/category-94-b0.html

8 回复

如果字段名称是用西里尔字母并带有空格书写的呢?

更多关于Golang中如何实现map和json的字段自动排序的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


为什么这在Go语言这边会是个问题呢?也许是在尝试将它们用作数据库列名时会出现问题……

因为我需要通过循环遍历所有数据来将数据填入动态表格。该表格包含约100个字段。
手动完成这项工作是不现实的。

igaisin:

我需要保持数据库中指定的字段顺序。

为什么?

Go 语言的 map 和 JSON 对象都不是有序的。{"a": 1, "b": 2}{"b": 2, "a": 1} 在 JSON 中是等效的。

标准映射是无序的 -

映射是由一组唯一键(称为键类型)索引的同一类型元素(称为元素类型)的无序集合。

您应该使用类似以下的有序集合: orderedmap

正确的方式是拥有一些额外的数据点来描述字段的顺序,例如一个字符串列表。遍历该列表并使用它来访问映射/对象中的字段。

// 代码示例
func main() {
    fields := []string{"field1", "field2", "field3"}
    data := map[string]interface{}{
        "field1": "value1",
        "field2": "value2", 
        "field3": "value3",
    }
    
    for _, field := range fields {
        fmt.Println(data[field])
    }
}

尝试将您检索的数据作为"本地"变量存储在YottaDB中。数据始终是排序的。更多信息请参阅https://docs.yottadb.com/MultiLangProgGuide/goprogram.html。值得一提的是,YottaDB还拥有分层键值数据库/持久化引擎(称为"全局"变量),但如果您已有数据库,可以直接将检索到的数据存储在YottaDB中而无需使用持久化引擎。

郑重声明:我负责领导YottaDB(https://yottadb.com & https://gitlab.com/YottaDB)。

此致 – Bhaskar

在Golang中,map[string]interface{}的键在JSON序列化时默认是无序的。要维持从数据库查询得到的字段顺序,可以使用有序的数据结构替代普通的map。以下是几种解决方案:

方案1:使用切片存储字段顺序

type OrderedMap struct {
    Keys   []string
    Values map[string]interface{}
}

func (om *OrderedMap) MarshalJSON() ([]byte, error) {
    var buf bytes.Buffer
    buf.WriteString("{")
    for i, key := range om.Keys {
        if i > 0 {
            buf.WriteString(",")
        }
        keyBytes, _ := json.Marshal(key)
        buf.Write(keyBytes)
        buf.WriteString(":")
        valBytes, _ := json.Marshal(om.Values[key])
        buf.Write(valBytes)
    }
    buf.WriteString("}")
    return buf.Bytes(), nil
}

// 使用示例
rows, _ := db.Query("SELECT * FROM table")
cols, _ := rows.Columns()
defer rows.Close()

d := make([]OrderedMap, 0)
for rows.Next() {
    columns := make([]interface{}, len(cols))
    columnPointers := make([]interface{}, len(cols))
    for i := range columns {
        columnPointers[i] = &columns[i]
    }

    rows.Scan(columnPointers...)

    m := OrderedMap{
        Keys:   cols,
        Values: make(map[string]interface{}),
    }
    for i, colName := range cols {
        val := columnPointers[i].(*interface{})
        m.Values[colName] = *val
    }

    d = append(d, m)
}

jsData, _ := json.Marshal(d)
w.Header().Set("Content-Type", "application/json")
w.Write(jsData)

方案2:使用第三方库(推荐)

安装有序map库:

go get github.com/iancoleman/orderedmap
import "github.com/iancoleman/orderedmap"

rows, _ := db.Query("SELECT * FROM table")
cols, _ := rows.Columns()
defer rows.Close()

d := make([]*orderedmap.OrderedMap, 0)
for rows.Next() {
    columns := make([]interface{}, len(cols))
    columnPointers := make([]interface{}, len(cols))
    for i := range columns {
        columnPointers[i] = &columns[i]
    }

    rows.Scan(columnPointers...)

    m := orderedmap.New()
    for i, colName := range cols {
        val := columnPointers[i].(*interface{})
        m.Set(colName, *val)
    }

    d = append(d, m)
}

jsData, _ := json.Marshal(d)
w.Header().Set("Content-Type", "application/json")
w.Write(jsData)

方案3:使用结构体切片(如果字段固定)

type Field struct {
    Key   string      `json:"key"`
    Value interface{} `json:"value"`
}

rows, _ := db.Query("SELECT * FROM table")
cols, _ := rows.Columns()
defer rows.Close()

d := make([][]Field, 0)
for rows.Next() {
    columns := make([]interface{}, len(cols))
    columnPointers := make([]interface{}, len(cols))
    for i := range columns {
        columnPointers[i] = &columns[i]
    }

    rows.Scan(columnPointers...)

    fields := make([]Field, len(cols))
    for i, colName := range cols {
        val := columnPointers[i].(*interface{})
        fields[i] = Field{
            Key:   colName,
            Value: *val,
        }
    }

    d = append(d, fields)
}

jsData, _ := json.Marshal(d)
w.Header().Set("Content-Type", "application/json")
w.Write(jsData)

推荐使用方案2的orderedmap库,它专门为解决这类问题设计,使用简单且性能良好。

回到顶部