英文:
Golang: insert nested structure model into Postgres
问题
我有这个模型数据结构:
type Order struct {
OrderEntry OrderEntry `db:"order"`
}
type OrderEntry struct {
Order_uid string
Track_number string
Entry string
Delivery Delivery
Payment Payment
Items []Item
Locale string
Internal_signature string
Customer_id string
Delivery_service string
Shardkey string
Sm_id int64
Date_created string
Oof_shard string
}
type Delivery struct {
// ...
}
type Payment struct {
// ...
}
type Item struct {
// ...
}
我有一个表:
CREATE TABLE "order"
(
"order" jsonb NOT NULL
);
我如何将Order对象插入到这个psq表中?我使用sqlx,但是在这段代码中我遇到了错误:
func (r *RepositoryPostgres) CreateDocument(order L0.Order) error {
tx := r.db.MustBegin()
tx.MustExec("INSERT INTO order (order) VALUES ($1)", order.OrderEntry)
err := tx.Commit()
if err != nil {
return err
}
return nil
}
错误信息为:panic: sql: converting argument $1 type: unsupported type L0.OrderEntry, a struct
如何正确修复这个问题?谢谢。
英文:
i have this model data structure:
type Order struct {
OrderEntry OrderEntry `db:"order"`
}
type OrderEntry struct {
Order_uid string
Track_number string
Entry string
Delivery Delivery
Payment Payment
Items []Item
Locale string
Internal_signature string
Customer_id string
Delivery_service string
Shardkey string
Sm_id int64
Date_created string
Oof_shard string
}
type Delivery struct {
...
}
type Payment struct {
...
}
type Item struct {
...
}
And i have table
CREATE TABLE "order"
(
"order" jsonb NOT NULL
);
How do i insert Order object to this psq table? I use sqlx and for this code im getting error
func (r *RepositoryPostgres) CreateDocument(order L0.Order) error {
tx := r.db.MustBegin()
tx.MustExec("INSERT INTO order (order) VALUES ($1)", order.OrderEntry)
err := tx.Commit()
if err != nil {
return err
}
return nil
}
panic: sql: converting argument $1 type: unsupported type L0.OrderEntry, a struct
How to properly fix this? Thanks
答案1
得分: 3
这里有几个你需要做的更改。
- 你需要将要存储的结构体转换为 JSON 格式。你可以使用以下代码实现:
orderB, err := json.Marshal(order.OrderEntry)
if err != nil {
// 处理错误
}
tx.MustExec("INSERT INTO order (order) VALUES ($1)", orderB)
这样会将你的结构体以 JSON 字节数组的形式存储到表中。
- 为了正确地从结构体生成 JSON,你需要为每个字段添加 JSON 结构标签。例如:
type OrderEntry struct {
Order_uid string `json:"order_uid"`
Track_number string `json:"track_number"`
Entry string `json:"entry"`
Delivery Delivery `json:"delivery"`
Payment Payment `json:"payment"`
Items []Item `json:"items"`
Locale string `json:"locale"`
Internal_signature string `json:"internal_signature"`
Customer_id string `json:"customer_id"`
Delivery_service string `json:"delivery_service"`
Shardkey string `json:"shard_key"`
Sm_id int64 `json:"sm_id"`
Date_created string `json:"date_created"`
Oof_shard string `json:"oof_shard"`
}
你可以根据需要自定义这些标签,通常使用蛇形命名法。这些标签为解析器提供了 JSON 字段的名称。
如果没有这些标签,你将得到一个空的 JSON,并且无法检索数据。
英文:
There are a couple of changes you need to make here.
- You need to marshal to JSON the struct you want to store. You can do that with:
orderB, err := json.Marshal(order.OrderEntry)
if err != nil {
// handle err
}
tx.MustExec("INSERT INTO order (order) VALUES ($1)", orderB)
This will now store your struct as a JSON byte-array in the table.
- In order to generate JSON from your struct correctly, you need to add JSON struct tags to each field. e.g.:
type OrderEntry struct {
Order_uid string `json:"order_uid"`
Track_number string `json:"track_number"`
Entry string `json:"entry"`
Delivery Delivery `json:"delivery"`
Payment Payment `json:"payment"`
Items []Item `json:"items"`
Locale string `json:"locale"`
Internal_signature string `json:"internal_signature"`
Customer_id string `json:"customer_id"`
Delivery_service string `json:"delivery_service"`
Shardkey string `json:"shard_key"`
Sm_id int64 `json:"sm_id"`
Date_created string `json:"date_created"`
Oof_shard string `json:"oof_shard"`
}
You can name these however you like, snake-case being the common format. These tags provide the names for the JSON fields to the parser.
Without these fields, you'll end up with empty JSON, and you won't be able to retrieve the data.
答案2
得分: 2
INSERT语句中不支持的类型"L0.OrderEntry"是导致你遇到问题的原因。由于"L0.OrderEntry"是"L0.Order"中的嵌套结构体,所以不能直接将其输入到JSONB列中。在将OrderEntry对象输入到表中之前,你需要将其转换为JSON表示。
你可以按照以下方式更改代码以解决错误。
import "encoding/json"
func (r *RepositoryPostgres) CreateDocument(order L0.Order) error {
tx := r.db.MustBegin()
orderJSON, error := json.Marshal(order.OrderEntry)
if error != nil {
return error
}
tx.MustExec("INSERT INTO order (order) VALUES ($1)", orderJSON)
error = tx.Commit()
if error != nil {
return error
}
return nil
}
修改后的代码使用"json.Marshal"方法将order.OrderEntry对象转换为JSON。生成的JSON字节切片(orderJSON)然后作为值提供给INSERT语句。
通过将嵌套结构体转换为JSON,你可以确保数据以正确的格式插入到JSONB列中。
英文:
The INSERT statement's unsupported type "L0.OrderEntry" is the cause of the issue you're experiencing. "L0.OrderEntry" cannot be directly entered into the JSONB column since it is a nested struct within "L0.Order". Instead, before entering the OrderEntry object into the table, you must marshal it into a JSON representation.
You can change your code as below to resolve the error.
import "encoding/json"
func (r *RepositoryPostgres) CreateDocument(order L0.Order) error {
tx := r.db.MustBegin()
orderJSON, error := json.Marshal(order.OrderEntry)
if error != nil {
return error
}
tx.MustExec("INSERT INTO order (order) VALUES ($1)", orderJSON)
error = tx.Commit()
if error != nil {
return error
}
return nil
}
The order.OrderEntry object is marshalled into JSON in the modified code using the "json.Marshal" method. The generated JSON byte slice (orderJSON) is then provided to the INSERT statement as the value.
You may make sure the data is in the correct format for insertion into the JSONB column by marshalling the nested struct into JSON.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论