Your Question

I redefine a type and implement interface driver.Value and driver.Scanner,for instance, I want type []string to be stored as a json string, but I need to update it to null even if it is a nil value.

type Example []string

// Value returns m as driver.Value
func (m Example) Value() (driver.Value, error) {
    bin, err := json.Marshal(m)
    return string(bin), err
}

func (m *Example) Scan(v interface{}) error {
    switch data := v.(type) {
    case string:
        return json.Unmarshal([]byte(data), m)
    case []byte:
        return json.Unmarshal(data, m)
    default:
        return fmt.Errorf("invalid value %v for Example to Scan", v)
    }
}

Expected answer

I suggest gorm offer an interface IsZero as a supplement to the method reflect.field.IsZero. Morever, a field tag nozerononil or something like that is also appreciated.

type Outer struct{
    Inner Example `gorm: "nozero"`
}

Comment From: jinzhu

Update zero fields https://gorm.io/docs/update.html#Update-Selected-Fields

Comment From: jinzhu

I don't think it is necessary to add another API to do the job, sounds like just a update zero-value fields issue, which is same if you are using other data types like: int, string?

Comment From: sdghchj

I don't think it is necessary to add another API to do the job, sounds like just a update zero-value fields issue, which is same if you are using other data types like: int, string?

Selecting explicitly actually does work for zero fields, but if my object has many fields, I don't think it is a good experience everytime to select every feild. Everytime I add or remove a field, I have to add or remove it in the select clause.

Comment From: jinzhu

If you want to select all fields, you can use db.Select("*")

Comment From: sdghchj

If you want to select all fields, you can use db.Select("*")

It is pity that usually there is a few fields that need not to update. More offen I use omit.

Comment From: jinzhu

Select("*").Omit("Name", "Age")

Comment From: sdghchj

go Select("*").Omit("Name", "Age")

e, ok

Comment From: jasonhp

go Select("*").Omit("Name", "Age")

It doesn't work. Select("*") still ignores all zero values.

Comment From: bencq

go Select("*").Omit("Name", "Age")

It doesn't work. Select("*") still ignores all zero values.

Yes, I also encountered this problem. Select("*") before Update() doesn't work.

Comment From: 0x9ef

I've faced the same trouble.

I guess it would be better to implement smth like gorm:"allowzero" tag. Why? There are 2 approaches to force zero fields. The first is to use a pointer and the second is to convert the structure to a map. These approaches have critical issues in my opinion.

Approach with a pointer: * We may don't want to use a pointer because it allows using nil as a value, in this way we will generate redundant checks for nil

Approach with converting a structure to a map: * It will provide a performance overhead. Because if a structure is too complex, in large production it would create unacceptable overhead costs

But, if we want to update an association with zero-value it will work.

Comment From: enzofoucaud

Any update ?

Select("*") don't work

Comment From: quolpr

@jinzhu sorry, but map interface looks really weird and unsafe. Could we still bring such an option?