英文:
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:
{
    "name": "Product1",
    "media": [
        "https://server.com/image1",
        "https://server.com/image2",
        "https://server.com/image3",
        "https://server.com/video1",
        "https://server.com/video2"
    ]
}
And I save a new product using this code
product := Product{}
if err := context.ShouldBindJSON(product); err != nil { // <-- here the error
	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
}
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(&product); err != nil {
			// handle err ...
			return
		}
		fmt.Println(product) // {Product1 [{"https://server.com/image1" 0} ... }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论