将 go struct 嵌入到 gorm 中的另一个结构中

Embed go struct into another struct in gorm

我有一个名为 http_requests 的数据库 table。我已经为以下结构建模以表示此 table.

中的行
type Map map[string]interface{}

type HTTPRequest struct {
   ID              int64     `json:"id" gorm:"id"`
   RequestURL      string    `json:"request_url,omitempty" gorm:"request_url"`
   RequestParams   *RequestParams  `json:"request_params,omitempty" gorm:"request_params"`
}


// RequestParams is another struct that holds params from body and URL query
type RequestParams struct {
    FromBody  Map `json:"body,omitempty"`
    FromQuery Map `json:"query,omitempty"`
}

保存 HTTPRequest 的代码:

request  := &HTTPRequest{
        RequestURL:      "dummy/url",
        RequestParams:   &RequestParams{FromBody: Map{"param1": "value1"}},
}

if err := gorm.DB.Create(request).Error; err != nil {
        return err
}

当我尝试保存此 HTTPRequest 时出现错误:

sql: Scan error on column index 9, name "request_params": unsupported Scan, storing driver.Value type []uint8 into type *RequestParams 

我希望有 request_params 列来存储 JSON,如下所示:

{"body":{"param1":"value1"}, "query": {"param2" : "value2"} }
or
{"body":{"param1":"value1"}}
or
{"query": {"param2" : "value2"} }

并且在从数据库中读取时应该将其解析为 RequestParams 结构。

按照@mkopriva 的建议,我为我的 RequestParams 类型实现了 Scan() 和 Value() 方法。请参阅下面的代码。


import (
    "database/sql/driver"
    "encoding/json"
    "strings"
)

// Value converts RequestParams to a map
func (reqParams RequestParams) Value() (driver.Value, error) {
    reqMap, err := reqParams.ToMap()

    if err != nil {
        return nil, err
    }

    return reqMap.ForceJSON(), nil
}

// Scan converts value to RequestParams
func (reqParams *RequestParams) Scan(value interface{}) error {
    // set empty struct by default
    *reqParams = RequestParams{}

    if value == nil {
        return nil
    }

    if s, ok := value.([]byte); ok {
        d := json.NewDecoder(strings.NewReader(string(s)))
        d.UseNumber()

        rp := &RequestParams{}
        if err := d.Decode(rp); err == nil {
            *reqParams = *rp
        }
    }

    return nil
}