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 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?