Go-Gin绑定具有一对多关系的数据

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

Go-Gin binding data with one-to-many relationship

问题

我是你的中文翻译助手,以下是翻译好的内容:

我对Golang和Gin框架还不熟悉,我创建了两个模型:

type Product struct {
    gorm.Model
    Name  string
    Media []Media
}

type Media struct {
    gorm.Model
    URI       string
    ProductID uint
}

然后我发送了一个POST请求来保存一个新的产品,请求体如下:

{
    "name": "Product1",
    "media": [
        "https://server.com/image1",
        "https://server.com/image2",
        "https://server.com/image3",
        "https://server.com/video1",
        "https://server.com/video2"
    ]
}

我使用以下代码保存了一个新的产品:

product := Product{}
if err := context.ShouldBindJSON(product); err != nil { // <-- 这里出错了
    context.String(http.StatusBadRequest, fmt.Sprintf("err: %s", err.Error()))
    return
}
tx := DB.Create(&product)
if tx.Error != nil {
    context.String(http.StatusBadRequest, fmt.Sprintf("err: %s", tx.Error))
    return
}

返回的错误信息是:

err: json: cannot unmarshal string into Go struct field Product.Media of type models.Media

我知道ShouldBindJSON无法将media-string转换为media-object,但是有什么最佳实践可以解决这个问题呢?

英文:

I'm new to Golang and Gin framework, I have created two models

type Product struct {
    gorm.Model
    Name string
    Media []Media
}

type Media struct {
	gorm.Model
	URI string
	ProductID uint
}

and I send a POST request to save a new product, the body was:

{
    &quot;name&quot;: &quot;Product1&quot;,
    &quot;media&quot;: [
        &quot;https://server.com/image1&quot;,
        &quot;https://server.com/image2&quot;,
        &quot;https://server.com/image3&quot;,
        &quot;https://server.com/video1&quot;,
        &quot;https://server.com/video2&quot;
    ]
}

And I save a new product using this code

product := Product{}
if err := context.ShouldBindJSON(product); err != nil { // &lt;-- here the error
	context.String(http.StatusBadRequest, fmt.Sprintf(&quot;err: %s&quot;, err.Error()))
	return
}
tx := DB.Create(&amp;product)
if tx.Error != nil {
	context.String(http.StatusBadRequest, fmt.Sprintf(&quot;err: %s&quot;, tx.Error))
	return
}

the return error message is

err: json: cannot unmarshal string into Go struct field Product.Media of type models.Media

I know that ShouldBindJSON can't convert media-string to media-object, but what is the best practice to do this?

答案1

得分: 1

你的有效载荷与模型不匹配。在JSON主体中,media是一个字符串数组,而在模型中它是一个具有两个字段的结构体<small>和嵌入的gorm模型</small>。

如果你不能改变当前设置的任何内容,可以在Media上实现UnmarshalJSON方法,并从原始字节中设置URI字段。在同一个方法中,如果需要,你还可以初始化ProductID为某个值。

func (m *Media) UnmarshalJSON(b []byte) error {
	m.URI = string(b)
	return nil
}

然后绑定将按预期工作:

product := Product{}
// 将指向product的指针传递
if err := context.ShouldBindJSON(&product); err != nil {
	// 处理错误...
	return
}
fmt.Println(product) // {Product1 [{"https://server.com/image1" 0} ... }
英文:

Your payload doesn't match the model. In the JSON body, media is an array of strings, whereas in the model it's a struct with two fields <small>and the embedded gorm model</small>.

If you can't change anything of your current setup, implement UnmarshalJSON on Media and set the URI field from the raw bytes. In the same method you may also initialize ProductID to something (if needed).

func (m *Media) UnmarshalJSON(b []byte) error {
	m.URI = string(b)
	return nil
}

Then the binding will work as expected:

		product := Product{}
        // pass a pointer to product
		if err := context.ShouldBindJSON(&amp;product); err != nil {
			// handle err ...
			return
		}
		fmt.Println(product) // {Product1 [{&quot;https://server.com/image1&quot; 0} ... }

huangapple
  • 本文由 发表于 2021年9月10日 00:00:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/69121393.html
匿名

发表评论

匿名网友

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

确定