douzheyo2617 2019-08-30 10:46
浏览 256
已采纳

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

I have a database table called http_requests. I have modelled following struct to represent rows in this 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"`
}

Code to save HTTPRequest:

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

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

When I try to save this HTTPRequest it results in error:

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

I would like to have request_params column to store JSON like this:

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

And this should get parsed into RequestParams struct when reading from database.

  • 写回答

1条回答 默认 最新

  • dou91808 2019-09-08 06:52
    关注

    As suggested by @mkopriva, I implemented Scan() and Value() methods for my RequestParams type. See code below.

    
    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
    }
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求解,我这个代码为什么运行不了
  • ¥15 remotes安装提示没有description文件
  • ¥15 AttributeError: 'NoneType' object has no attribute 'drop_duplicates'报错
  • ¥15 以下代码,运行结果报错
  • ¥15 Vivado仿真数据出错
  • ¥15 银河麒麟不支持vant等前端框架怎么办?
  • ¥15 vue3的子组件在父页面调用不显示不生效问题
  • ¥15 cadence PEX
  • ¥15 phython创建了文件 显示在项目下面,但运行不了,运行时还是运行main文件,并且说main文件不允许并行运行
  • ¥15 FutureWarning:不推荐使用空或全 NA 条目的 DataFrame 串联行为。怎么改呢?