使用Go官方MongoDB驱动将对象数组转存为结构体切片报错求助
问题解决与实现方案
报错原因分析
panic: invalid character 'l' looking for beginning of object key string 通常由以下两种情况导致:
- 结构体字段映射不匹配:你的
MongoFields结构体中DataType字段的bson标签是data_type,但MongoDB中的实际字段是dataType(驼峰命名),解码时字段不匹配引发解析错误。 - 错误解析非标准JSON:若你直接将Mongo Shell输出的非严格JSON(使用单引号、无引号键)当作JSON字符串解析,也会触发该格式错误。
修正后的结构体
首先修正结构体的bson标签,确保与MongoDB字段完全匹配:
import "go.mongodb.org/mongo-driver/bson" type MongoFields struct { Field string `bson:"field" json:"field"` FieldKey string `bson:"field_key,omitempty" json:"field_key,omitempty"` DataType string `bson:"dataType" json:"dataType"` // 修正bson标签为dataType Order int `bson:"order,omitempty" json:"order,omitempty"` CatAttrib bson.M `bson:"catAttrib,omitempty" json:"catAttrib,omitempty"` } // 临时结构体用于接收顶层查询结果 type ConfigResult struct { ListAttributes map[string]MongoFields `bson:"list_attributes"` }
完整实现代码
通过官方MongoDB驱动查询数据,并将list_attributes(键为数字字符串的对象)转换为有序切片:
package main import ( "context" "fmt" "sort" "strconv" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) type MongoFields struct { Field string `bson:"field" json:"field"` FieldKey string `bson:"field_key,omitempty" json:"field_key,omitempty"` DataType string `bson:"dataType" json:"dataType"` Order int `bson:"order,omitempty" json:"order,omitempty"` CatAttrib bson.M `bson:"catAttrib,omitempty" json:"catAttrib,omitempty"` } type ConfigResult struct { ListAttributes map[string]MongoFields `bson:"list_attributes"` } func main() { // 连接MongoDB clientOpts := options.Client().ApplyURI("mongodb://localhost:27017") client, err := mongo.Connect(context.TODO(), clientOpts) if err != nil { panic(err) } defer client.Disconnect(context.TODO()) // 选择目标集合 coll := client.Database("your_db_name").Collection("config") // 查询并解码结果 var result ConfigResult projection := bson.D{{Key: "list_attributes", Value: 1}, {Key: "_id", Value: 0}} err = coll.FindOne(context.TODO(), bson.D{}, options.FindOne().SetProjection(projection)).Decode(&result) if err != nil { panic(err) } // 将map转换为有序切片 // 提取并排序键(转换为整数) keys := make([]int, 0, len(result.ListAttributes)) for k := range result.ListAttributes { num, err := strconv.Atoi(k) if err != nil { continue // 跳过非数字键(如果有的话) } keys = append(keys, num) } sort.Ints(keys) // 按顺序填充切片 fieldsSlice := make([]MongoFields, len(keys)) for i, key := range keys { fieldsSlice[i] = result.ListAttributes[strconv.Itoa(key)] } // 验证结果 fmt.Printf("转换后的切片:\n%+v\n", fieldsSlice) }
关键实现说明
- 字段映射修正:确保结构体的bson标签与MongoDB中的字段名严格一致,避免解码失败。
- 对象转切片:由于MongoDB中的
list_attributes是键为数字字符串的对象而非数组,需要先提取所有键,转换为整数并排序,再按顺序填充到切片中,保证切片索引与原对象的数字键对应。 - 正确使用驱动:通过官方驱动直接查询BSON数据并解码,避免手动解析非标准JSON引发的格式错误。
内容的提问来源于stack exchange,提问作者Arun Suryan
相关产品推荐
相关产品推荐

