英文:
Golang Gin Binding Request body XML to Slice
问题
我在Gin中遇到了默认绑定的问题。我有一个传入请求,其中请求体是多个Entity对象,如下所示:
<Entity>
<Name>这里是名称一</Name>
...
</Entity>
<Entity>
<Name>这里是名称二</Name>
...
</Entity>
我的目标是将其映射到相应的切片。所以期望对象的结构如下所示:
type Entity struct {
XMLName xml.Name `bson:"- json:"- xml:"Entity"`
Name string `bson:"name,omitempty" json:",omitempty" xml:",omitempty"`
...
}
我遇到的问题是,只有一个提供的对象被映射到切片中,无论请求体中传递了多少个对象。请注意,请求的JSON版本解析正确。
[
{
Name: "名称一",
...
},
{
Name: "名称二",
...
}
]
我有一个用于建模请求结构的结构体:
type ApplicationRequest struct {
XMLName xml.Name `bson:"- xml:"Entities"`
Entities []Entity `binding:"required" xml:"Entity"`
ParameterOne bool
...
}
所以现在在控制器函数中,我这样处理绑定:
func RequestHandler() gin.HandlerFunc {
return func(c *gin.Context) {
var request ApplicationRequest
if err := c.Bind(&request.Entities); err != nil {
responseFunction(http.StatusBadRequest, ..., Message: err.Error()})
return
}
// 此时,request.Entities切片只有一个元素,永远不会超过一个
}
}
请注意,我使用gin的context.Bind(...)函数,因为它隐式地处理JSON或XML的解析,并且适用于我需要的所有其他场景。
希望这提供了足够的上下文,非常感谢任何帮助!谢谢!
英文:
I am having an issue with the default binding in Gin. I have an incoming request where the body is multiple Entity objects like so:
<Entity>
<Name>Name One here</Name>
...
</Entity>
<Entity>
<Name>Name Two here</Name>
...
</Entity>
My goal is to map it to a corresponding slice. So the struct for the desired object is like so:
type Entity struct {
XMLName xml.Name `bson:"-" json:"-" xml:"Entity"`
Name string `bson:"name,omitempty" json:",omitempty" xml:",omitempty"`
...
}
The problem I'm experiencing is that only one of the supplied objects is ever mapped into the slice, regardless of how many are passed in the request body. Note that the JSON version of the request parses correctly.
[
{
Name: "Name One",
...
},
{
Name: "Name Two",
...
}
]
I have a struct to model request structure
type ApplicationRequest struct {
XMLName xml.Name `bson:"-" xml:"Entities"`
Entities []Entity `binding:"required" xml:"Entity"`
ParameterOne bool
...
}
So now within the controller function, I handle the binding like this:
func RequestHandler() gin.HandlerFunc {
return func(c *gin.Context) {
var request ApplicationRequest
if err := c.Bind(&request.Entities); err != nil {
responseFunction(http.StatusBadRequest, ..., Message: err.Error()})
return
}
// At this point, the request.Entities slice has ONE element, never more than one
}
}
Note I'm using the gin context.Bind(...) function because it handles the parsing of JSON or XML implicitly, and works for all other scenarios that I need.
Hopefully this provides enough context, any help would be greatly appreciated! Thanks!
答案1
得分: 2
这是一个关于在Golang中解析XML数组时只获取第一个元素的问题。提供了两种解决方法:
- 添加一个根节点,就像@zangw所建议的那样。
- 通过使用
for
循环来更改绑定方法。在github.com/gin-gonic/gin@v1.8.1/binding/xml.go
文件的第28行,将func decodeXML
的实现从原来的代码改为以下代码:
func decodeXML(r io.Reader, obj any) error {
decoder := xml.NewDecoder(r)
for {
if err := decoder.Decode(obj); err != nil {
if err == io.EOF {
break
}
return err
}
}
return validate(obj)
}
希望对你有帮助!
英文:
it is not a gin problem:
unmarshal-xml-array-in-golang-only-getting-the-first-element
follow is two way to deal it:
-
add a root node just like @zangw
-
change the bind method by 'for'
github.com\gin-gonic\gin@v1.8.1\binding\xml.go
line 28
func decodeXML
from
func decodeXML(r io.Reader, obj any) error {
decoder := xml.NewDecoder(r)
if err := decoder.Decode(obj); err != nil {
return err
}
return validate(obj)
}
to
func decodeXML(r io.Reader, obj any) error {
decoder := xml.NewDecoder(r)
for {
if err := decoder.Decode(obj); err != nil {
if err == io.EOF{
break
}
return err
}
}
return validate(obj)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论