Skip to content

Commit e98dccc

Browse files
authored
Fix nil pointer panic in serializer for nil any-type fields (#7634)
* Fix nil pointer panic when using any type field with nil Serializer * test: add test case for serializer with any type
1 parent 6e7eb0a commit e98dccc

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

schema/field.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,13 @@ func (field *Field) setupValuerAndSetter(modelType reflect.Type) {
962962
serializerType := serializerValue.Type()
963963
field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
964964
if s, ok := v.(*serializer); ok {
965+
if s.fieldValue == nil && s.Serializer == nil {
966+
rv := field.ReflectValueOf(ctx, value)
967+
if rv.IsValid() && rv.CanSet() {
968+
rv.Set(reflect.Zero(field.FieldType))
969+
}
970+
return nil
971+
}
965972
if s.fieldValue != nil {
966973
err = oldFieldSetter(ctx, value, s.fieldValue)
967974
} else if err = s.Serializer.Scan(ctx, field, value, s.value); err == nil {

tests/serializer_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,3 +227,59 @@ func TestSerializerAssignFirstOrCreate(t *testing.T) {
227227
AssertEqual(t, result.Roles, data.Roles)
228228
AssertEqual(t, result.JobInfo.Location, data.JobInfo.Location)
229229
}
230+
231+
// Test for: panic when serializer field with any type is nil
232+
func TestSerializerWithAnyType(t *testing.T) {
233+
type ProductWithAny struct {
234+
gorm.Model
235+
Name string
236+
Data any `gorm:"serializer:json"`
237+
}
238+
239+
DB.Migrator().DropTable(&ProductWithAny{})
240+
if err := DB.AutoMigrate(&ProductWithAny{}); err != nil {
241+
t.Fatalf("failed to migrate ProductWithAny, got error %v", err)
242+
}
243+
244+
// Test creating record with nil any field
245+
product := ProductWithAny{Name: "Product 1"}
246+
if err := DB.Create(&product).Error; err != nil {
247+
t.Fatalf("failed to create product with nil any field, got error %v", err)
248+
}
249+
250+
// Test updating/saving record with nil any field (should not panic)
251+
product.Name = "Product 1 (Updated)"
252+
if err := DB.Save(&product).Error; err != nil {
253+
t.Fatalf("failed to save product with nil any field, got error %v", err)
254+
}
255+
256+
// Verify the record was saved correctly
257+
var result ProductWithAny
258+
if err := DB.First(&result, product.ID).Error; err != nil {
259+
t.Fatalf("failed to query product, got error %v", err)
260+
}
261+
262+
if result.Name != "Product 1 (Updated)" {
263+
t.Errorf("expected name to be 'Product 1 (Updated)', got %s", result.Name)
264+
}
265+
266+
if result.Data != nil {
267+
t.Errorf("expected Data to be nil, got %v", result.Data)
268+
}
269+
270+
// Test with non-nil value
271+
dataValue := map[string]interface{}{"key": "value"}
272+
product2 := ProductWithAny{Name: "Product 2", Data: dataValue}
273+
if err := DB.Create(&product2).Error; err != nil {
274+
t.Fatalf("failed to create product with non-nil any field, got error %v", err)
275+
}
276+
277+
var result2 ProductWithAny
278+
if err := DB.First(&result2, product2.ID).Error; err != nil {
279+
t.Fatalf("failed to query product2, got error %v", err)
280+
}
281+
282+
if result2.Data == nil {
283+
t.Error("expected Data to be non-nil")
284+
}
285+
}

0 commit comments

Comments
 (0)