如何从XML的Item块反序列化数据并通过GORM存入数据库
Go语言XML反序列化+GORM存储:正确保存嵌套Item块字段的方案
问题场景
从API获取的XML结构如下,顶层<rates>和嵌套<item>块都包含name、title字段:
<rates> <name>text1</name> <title>text2</title> <item> <name>text3</name> <title>text4</title> </item> </rates>
当前代码只能保存顶层Rates的字段,无法存储Item块的内容,需要修改代码实现Item字段的数据库存储。原代码如下:
type Rates struct { XMLName xml.Name `xml:"rates"` Rates []Item `xml:"item"` } type Item struct { Id int `xml:"id" gorm:"primaryKey"` Name string `xml:"name"` Title string `xml:"title"` } response, err := http.Get("https://API") responseData, err := io.ReadAll(response.Body) var var1 Item xml.Unmarshal(responseData, &var1) if result := h.DB.Create(&var1); result.Error != nil { fmt.Println(result.Error) } w.Header().Add("Content-Type", "application/xml") w.WriteHeader(http.StatusOK) xml.NewEncoder(w).Encode(var1)
问题分析与修复方案
1. 核心问题:反序列化目标不匹配
当前代码直接把XML反序列化为Item类型,但XML根节点是<rates>,必须先反序列化为Rates类型,才能拿到嵌套的item列表数据。
2. 结构体优化与修正
Rates结构体里的Rates字段名语义模糊,建议改成Items,同时确保xml标签正确对应<item>节点;Item的Id字段去掉xml:"id"标签,因为XML里没有<id>节点,避免反序列化失败(主键ID由数据库自增生成即可);- 如果需要保存顶层Rates的
name和title,给Rates结构体添加对应字段。
3. 完整修正代码
import ( "encoding/xml" "io" "net/http" "gorm.io/gorm" ) type Rates struct { XMLName xml.Name `xml:"rates"` Items []Item `xml:"item"` // 修正字段名,语义更清晰 Name string `xml:"name"` // 可选:保存顶层Rates的name Title string `xml:"title"`// 可选:保存顶层Rates的title } type Item struct { Id int `gorm:"primaryKey"` // 去掉xml标签,数据库自增生成ID Name string `xml:"name"` Title string `xml:"title"` } // 处理请求的核心逻辑 func handleRequest(w http.ResponseWriter, r *http.Request, DB *gorm.DB) { response, err := http.Get("https://API") if err != nil { w.WriteHeader(http.StatusInternalServerError) return } defer response.Body.Close() responseData, err := io.ReadAll(response.Body) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } // 反序列化为Rates类型,匹配XML根节点 var rates Rates err = xml.Unmarshal(responseData, &rates) if err != nil { w.WriteHeader(http.StatusBadRequest) return } // 批量存入所有Item,比逐个插入更高效 if len(rates.Items) > 0 { if result := DB.Create(&rates.Items); result.Error != nil { w.WriteHeader(http.StatusInternalServerError) return } } // 返回Item数据(示例:返回所有Item) w.Header().Add("Content-Type", "application/xml") w.WriteHeader(http.StatusOK) xml.NewEncoder(w).Encode(rates.Items) }
关键修改说明
- 反序列化目标从
Item改为Rates,才能正确解析嵌套的<item>节点; - 批量插入
rates.Items提升数据库操作效率; - 去掉
Item.Id的xml标签,避免因XML无<id>节点导致的反序列化错误。
内容的提问来源于stack exchange,提问作者Epic555
相关产品推荐
相关产品推荐

