Golang运行时无结构生成JSON数据的实现方法

Golang运行时无结构生成JSON数据的实现方法

func queryToJson(db *sql.DB, query string, args …interface{}) ([]byte, error) {
// 一个 JSON 对象数组
// map 的键是字段名
var objects []map[string]interface{}

    rows, err := db.Query(query, args...)
    if err != nil {
    	return nil, err
    }
    for rows.Next() {
    	// 找出返回了哪些列
    	// 列名将成为 JSON 对象的字段键
    	columns, err := rows.ColumnTypes()
    	if err != nil {
    		return nil, err
    	}
    
    	// Scan 需要一个指向它所设置值的指针数组
    	// 这会创建对象并正确设置值
    	values := make([]interface{}, len(columns))
    	object := map[string]interface{}{}
    	for i, column := range columns {
    		object[column.Name()] = reflect.New(column.ScanType()).Interface()
    		values[i] = object[column.Name()]
    	}
    
    	err = rows.Scan(values...)
    	if err != nil {
    		return nil, err
    	}
    
    	objects = append(objects, object)
    }
    
    // 使用缩进,因为我想阅读输出
    return json.MarshalIndent(objects, "", "\t")

}

这段代码可以工作。我希望列的顺序与数据库表的字段顺序一致。


更多关于Golang运行时无结构生成JSON数据的实现方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang运行时无结构生成JSON数据的实现方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,使用sql.Rows查询数据库并生成JSON时,保持列顺序确实是一个常见需求。以下是改进后的代码实现,确保JSON字段顺序与数据库表字段顺序一致:

func queryToJson(db *sql.DB, query string, args ...interface{}) ([]byte, error) {
    rows, err := db.Query(query, args...)
    if err != nil {
        return nil, err
    }
    defer rows.Close()

    colTypes, err := rows.ColumnTypes()
    if err != nil {
        return nil, err
    }

    colNames := make([]string, len(colTypes))
    for i, ct := range colTypes {
        colNames[i] = ct.Name()
    }

    var result []map[string]interface{}
    
    for rows.Next() {
        values := make([]interface{}, len(colTypes))
        for i := range values {
            var v interface{}
            values[i] = &v
        }
        
        if err := rows.Scan(values...); err != nil {
            return nil, err
        }
        
        obj := make(map[string]interface{}, len(colTypes))
        for i, colName := range colNames {
            val := *values[i].(*interface{})
            obj[colName] = val
        }
        result = append(result, obj)
    }

    if err := rows.Err(); err != nil {
        return nil, err
    }

    return json.MarshalIndent(result, "", "\t")
}

如果需要更严格地保持顺序,可以使用有序的map结构:

import (
    "encoding/json"
    "database/sql"
    "github.com/iancoleman/orderedmap"
)

func queryToOrderedJson(db *sql.DB, query string, args ...interface{}) ([]byte, error) {
    rows, err := db.Query(query, args...)
    if err != nil {
        return nil, err
    }
    defer rows.Close()

    colTypes, err := rows.ColumnTypes()
    if err != nil {
        return nil, err
    }

    var result []*orderedmap.OrderedMap
    
    for rows.Next() {
        values := make([]interface{}, len(colTypes))
        for i := range values {
            var v interface{}
            values[i] = &v
        }
        
        if err := rows.Scan(values...); err != nil {
            return nil, err
        }
        
        obj := orderedmap.New()
        for i, ct := range colTypes {
            val := *values[i].(*interface{})
            obj.Set(ct.Name(), val)
        }
        result = append(result, obj)
    }

    if err := rows.Err(); err != nil {
        return nil, err
    }

    return json.MarshalIndent(result, "", "\t")
}

第一个实现使用标准库,虽然Go的JSON包不保证map的顺序,但在实践中通常按字母顺序输出。第二个实现使用orderedmap第三方库,可以确保JSON字段完全按照数据库列的顺序输出。

回到顶部