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!
CodePudding user response:
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\[email protected]\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)
}