Golang Gin将请求体XML绑定到切片

huangapple go评论77阅读模式
英文:

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:

&lt;Entity&gt;
  &lt;Name&gt;Name One here&lt;/Name&gt;
  ...
&lt;/Entity&gt;
&lt;Entity&gt;
  &lt;Name&gt;Name Two here&lt;/Name&gt;
  ...
&lt;/Entity&gt;

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:&quot;-&quot; json:&quot;-&quot; xml:&quot;Entity&quot;`
  Name   string    `bson:&quot;name,omitempty&quot; json:&quot;,omitempty&quot; xml:&quot;,omitempty&quot;`
  ...
}

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: &quot;Name One&quot;,
   ...
 },
 {
   Name: &quot;Name Two&quot;,
   ...
 }
]

I have a struct to model request structure

type ApplicationRequest struct {
  XMLName      xml.Name `bson:&quot;-&quot; xml:&quot;Entities&quot;`
  Entities     []Entity `binding:&quot;required&quot; xml:&quot;Entity&quot;`
  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(&amp;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数组时只获取第一个元素的问题。提供了两种解决方法:

  1. 添加一个根节点,就像@zangw所建议的那样。
  2. 通过使用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)
}

huangapple
  • 本文由 发表于 2022年10月28日 02:14:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/74226570.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定