英文:
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} ... }
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论