英文:
Custom string to bool conversion for sql/driver and Gorm
问题
我正在尝试创建一个字符串到布尔值的转换数据类型,为了进一步解释我想要实现的目标,我将给出一个字符串连接的示例。
当使用gorm时,以下结构体在字段2和字段3处会失败,如果你调试它,它基本上会抛出一个错误,错误信息为sql: Scan error on column index 2, name "nlfieldTwo": unsupported Scan, storing driver.Value type []uint8 into type *[]string;
type Name struct {
FieldOne *String `json:"fieldOne,omitempty" gorm:"column:nlfieldOne"`
FieldTwo *[]String `json:"fieldTwo,omitempty" gorm:"column:nlfieldTwo"`
FieldThree *[]String `json:"fieldThree,omitempty" gorm:"column:nlfieldThree"`
}
解决方法是创建自己的类型:
type StringConcat []string
func (s *StringConcat) Scan(value interface{}) error {
str, _ := value.([]byte)
*s = strings.Split(string(str), ",")
return nil
}
func (s StringConcat) Value() (driver.Value, error) {
if len(s) == 0 {
return nil, nil
}
return strings.Join(s, ","), nil
}
然后将FieldTwo *[]String
替换为FieldTwo StringConcat
。
问题
我想为布尔类型做类似的处理,就像FieldFour
中所示:
type Name struct {
FieldOne *String `json:"fieldOne,omitempty" gorm:"column:nlfieldOne"`
FieldTwo *[]String `json:"fieldTwo,omitempty" gorm:"column:nlfieldTwo"`
FieldThree *[]String `json:"fieldThree,omitempty" gorm:"column:nlfieldThree"`
FieldFour *bool `json:"fieldThree,omitempty" gorm:"column:nlfieldFour"`
}
FieldFour
是一个字符串类型,所以如果我尝试上述方法,它将会失败并抛出错误sql: Scan error on column index 2, name "nlfieldFour": sql/driver: couldn't convert "" into type bool; sql: Scan error on column index 2, name "nlfieldFour": sql/driver: couldn't convert "None" into type bool; sql: Scan error on column index 2, name "nlfieldFour": sql/driver: couldn't convert "Creative" into type bool; ....... and so on
。
我想将其转换为布尔值,但是,我不想检查空字符串和"None"字符串值,如上面的错误所示,只要它们是其他字符串值,我希望返回true,如果没有值,则返回false。
我尝试查看strconv.FormatBool
,但是我无法找到一种方法来实现这个。
英文:
I am trying to create a string to bool converstion data type, to further explain what I am trying to achieve I will give an example of a string concat.
The following struct will fail at field 2 and 3 when using gorm, if you debug this it will basically throw an error saying sql: Scan error on column index 2, name "nlfieldTwo": unsupported Scan, storing driver.Value type []uint8 into type *[]string;
type Name struct {
FieldOne *String `json:"fieldOne,omitempty" gorm:"column:nlfieldOne"`
FieldTwo *[]String `json:"fieldTwo,omitempty" gorm:"column:nlfieldTwo"`
FieldThree *[]String `json:"fieldThree,omitempty" gorm:"column:nlfieldThree"`
}
A fix around this is to create your own type
type StringConcat []string
func (s *StringConcat) Scan(value interface{}) error {
str, _ := value.([]byte)
// log.Println(value)
// if !ok {
// return errors.New(fmt.Sprint("Failed to unmarshal value:", value))
// }
*s = strings.Split(string(str), ",")
return nil
}
// Value return json value, implement driver.Valuer interface
func (s StringConcat) Value() (driver.Value, error) {
if len(s) == 0 {
return nil, nil
}
return strings.Join(s, ","), nil
}
and then simply replace FieldTwo *[]String
with FieldTwo StringConcat
THE PROBLEM
I am trying to do something similar for a bool type as seen in FieldFour
type Name struct {
FieldOne *String `json:"fieldOne,omitempty" gorm:"column:nlfieldOne"`
FieldTwo *[]String `json:"fieldTwo,omitempty" gorm:"column:nlfieldTwo"`
FieldThree *[]String `json:"fieldThree,omitempty" gorm:"column:nlfieldThree"`
FieldFour *bool `json:"fieldThree,omitempty" gorm:"column:nlfieldFour"`
}
FieldFour is a string type so if I try doing the above it will simply fail and throw an error sql: Scan error on column index 2, name "nlfieldFour": sql/driver: couldn't convert "" into type bool; sql: Scan error on column index 2, name "nlfieldFour": sql/driver: couldn't convert "None" into type bool; sql: Scan error on column index 2, name "nlfieldFour": sql/driver: couldn't convert "Creative" into type bool; ....... and so on
I am trying to convert that to return a bool however, I do not want to check for empty and None string values as shown in the error above ""
and "None"
everything else I want to return a true if they got a string value or false if they got nothing.
I tried looking into strconv.FormatBool
but I could not figure out a way of doing this.
答案1
得分: 1
这应该可以通过实现自定义类型来实现:
type MyBool bool
func (s *MyBool) Scan(value interface{}) error {
b, _ := value.(string)
if b == "" || b == "None" {
*s = false
} else {
*s = true
}
return nil
}
func (s MyBool) Value() (driver.Value, error) {
if s {
return "true", nil
}
return "", nil
}
我不确定我是否正确理解了所需的映射,但你应该能够进行调整。在Scan
中定义你的string
到bool
的映射,反之亦然在Value
中定义。
英文:
That should be doable by implementing your custom type as well:
type MyBool bool
func (s *MyBool) Scan(value interface{}) error {
b, _ := value.(string)
if b == "" || b == "None" {
*s = false
} else {
*s = true
}
return nil
}
func (s MyBool) Value() (driver.Value, error) {
if s {
return "true", nil
}
return "", nil
}
I'm not sure, if I understood the required mapping right, but you should be able to adapt it. Define your mapping of string
to bool
in Scan
and vice versa in Value
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论