Golang存储数据到MongoDB时出现空值问题排查求助
Golang:API JSON转结构体存入MongoDB全为默认值的排查与解决
问题核心原因
JSON反序列化结构不匹配
API返回的是map[string]Currency格式(每个键对应一个完整的Currency对象),但你用map[string]Rate接收。Rate结构体中嵌入的Currency字段带有json:"currency"标签,意味着反序列化时会去寻找名为currency的子字段,但API返回的每个对象直接是Currency的平级字段,没有嵌套在currency下,导致Currency的所有字段无法被赋值,只能使用默认值。MongoDB序列化标签缺失
Currency结构体未定义bson标签,存入Mongo时字段名会被自动转为小写蛇形(如AlphaCode变成alphacode),虽然这不是默认值问题的直接原因,但会导致存储的字段名不符合预期。
解决步骤与代码修改
1. 修正结构体定义(model.go)
根据需求选择两种方案之一:
方案A:保留Mongo中的currency嵌套结构
type Currency struct { Code string `json:"code" bson:"code"` AlphaCode string `json:"alphaCode" bson:"alphaCode"` NumericCode string `json:"numericCode" bson:"numericCode"` Name string `json:"name" bson:"name"` Rate float64 `json:"rate" bson:"rate"` Date string `json:"date" bson:"date"` InverseRate float64 `json:"inverseRate" bson:"inverseRate"` } type Rate struct { ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` Currency Currency `json:"currency" bson:"currency"` // 改为显式结构体字段,而非嵌入 Timestamp primitive.DateTime `json:"timestamp" bson:"timestamp"` }
方案B:将Currency字段直接嵌入Mongo文档(无嵌套)
type Currency struct { Code string `json:"code" bson:"code"` AlphaCode string `json:"alphaCode" bson:"alphaCode"` NumericCode string `json:"numericCode" bson:"numericCode"` Name string `json:"name" bson:"name"` Rate float64 `json:"rate" bson:"rate"` Date string `json:"date" bson:"date"` InverseRate float64 `json:"inverseRate" bson:"inverseRate"` } type Rate struct { ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` Currency `bson:",inline"` // 用inline标签让Currency字段直接嵌入 Timestamp primitive.DateTime `json:"timestamp" bson:"timestamp"` }
2. 修正API数据反序列化逻辑
无论选择哪种方案,都需要先将API返回的JSON反序列化为map[string]Currency,再转换为map[string]Rate:
const apiUrl = "https://www.floatrates.com/daily/aud.json" func GetRatesFromAPI() (map[string]models.Rate, error) { response, err := http.Get(apiUrl) if err != nil { return nil, err } defer response.Body.Close() body, err := ioutil.ReadAll(response.Body) if err != nil { return nil, err } // 先匹配API结构,反序列化为map[string]Currency var currencyMap map[string]models.Currency if err := json.Unmarshal(body, ¤cyMap); err != nil { return nil, err } // 转换为需要的Rate结构 rateMap := make(map[string]models.Rate, len(currencyMap)) for key, curr := range currencyMap { rateMap[key] = models.Rate{ Currency: curr, // 方案A的赋值方式;方案B同样适用 } } return rateMap, nil }
3. 调试验证建议
- 反序列化后打印
currencyMap,确认API返回的数据是否被正确解析 - 转换为
rateMap后打印单个Rate对象,检查Currency字段是否有有效值 - 存入Mongo前打印最终要插入的Rate对象,确保数据正确
内容的提问来源于stack exchange,提问作者Piter Penn
相关产品推荐
相关产品推荐

