How to access other field of the model from custom serializer

I need to deserialize to various data types based on the value of the type field. For ex. if type is "int" then i'll deserialize db value into an int, same way it'll be done for float, string and bool.

I've searched for this in the docs & the issues tab but I think I didn't found it.

Here's my model

type Setting struct {
    ID uint `json:"id" gorm:"primaryKey"`

    Key            string                   `json:"key" gorm:"type:varchar(80); not null;uniqueIndex;"`
    Value          serializers.SettingValue `json:"value" gorm:"type:text;"`
    Type           string                   `json:"type" gorm:"type:varchar(100); not null;"`
    // ....

    CreatedAt time.Time `json:"created_at" gorm:"type:datetime"`
    UpdatedAt time.Time `json:"updated_at" gorm:"type:datetime"`
}

Here's the serializer

type SettingValue struct {
    Val any `json:"val"`
}

// Scan implements schema.SerializerInterface (db out)
func (sv *SettingValue) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) (err error) {

    // find out the type (---- THIS step is crucial to determine the deserialization data type)
        dst.Elem().FieldByName("Type") // ""

        // becuse the following
        // fmt.Printf("dxx %#v \n", dst.Elem())
        // produces following (only ID & Key has value others (after current field) are zero value, but the db has value for them
        //model.Setting{
    //  ID:0x1,
    //  Key:"test_1",
        //      Type: "",
    //  Value:serializers.SettingValue{Val:interface {}(nil)},
    //  // ...
    //  CreatedAt:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC),
    //  UpdatedAt:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC)
    //}

    // decode value base on the type

    switch val := dbValue.(type) {
    case []byte:
        sv.Val = bytes.NewBuffer(val).String()

    default:
        err = fmt.Errorf("unsupported data type (%T) in value", val)

    }

    return
}

// Value implements schema.SerializerInterface (db in)
func (*SettingValue) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
    sv, ok := fieldValue.(SettingValue)
    if !ok {
        return nil, errors.New("setting value field should be type of SettingValue")
    }

    var r any

    switch v := sv.Val.(type) {
    case string, int, uint, float64, bool:
        r = v
    default:
        return nil, fmt.Errorf("invalid value type %T in field %s", fieldValue, field.Name)
    }

    return r, nil
}

DB Values (response from the handler)

 [
      {
            "id": 1,
            "key": "test_1",
            "value": {
                "val": "27"
            },
            "type": "int",
            // ...
            "created_at": "2024-04-04T13:17:04+06:00",
            "updated_at": "2024-04-04T13:17:04+06:00"
        }
]

The document you expected this should be explained

This should be covered in details in: https://gorm.io/docs/serializer.html

Expected answer

First, I'm not getting why except ID & Key field all fields are empty when accessing from dst.Elem() in Scan fn. I expect to know how to get other fields value of the model from (this) custom serializer.

Another: I've noticed if I do this sv.Val = val in the case []byte block the value in response gets base64 encoded. whats the reason could be?

Comment From: apuatcfbd

I'm new in GO and GORM. Probably I'm doing something wrong. Please excuse it if possible. I've tried but failed to accomplish the task & lastly came here for help. As the case is not covered in the docs I think this'll be helpful for others, specially newbies like me. I'll highly appreciate it if anybody shade some light on this. Thanks

Comment From: apuatcfbd

Hi, I'll appreciate any help on this matter.

Comment From: jinzhu

The values of other fields can be found in dst. If their values are empty, it might be because the custom serializer field were scanned before the other fields. this depends on the order of the query fields.

Comment From: apuatcfbd

Thank you, In my case, this is the case (other fields are zero value). How to resolve this?