Partial updates of objects

2.1k Views Asked by At

I want to enable update functionality for my User object in my fiber/gorm backend. It works fine when I update all fields together using the Save function. However, when I do not have all fields present in the update request (for example only the Birthday field but not the Phone field) it overwrites the rest of the fields with their respective null values.

func UserUpdateByID(c *fiber.Ctx) error {
    db := database.DBConn

    // Parse the body to fit user entity
    user := entities.User{}
    if err := c.BodyParser(&user); err != nil {
        return c.Status(500).SendString(err.Error())
    }

    // Update record
    record := db.Save(&user)
    if record.Error != nil {
        return c.Status(500).SendString(record.Error.Error())
    }
return c.JSON(record.Value)

When I change the line with record := db.Save(&user) to

mappedData, _ := StructToMap(user)
record := db.Model(&entities.User{}).Update(mappedData)

I receive the error that Update can not handle map of interfaces: sql: converting argument $10 type: unsupported type map[string]interface {}, a map

Update 1: The mentioned StructToMap function looks like this:

func StructToMap(obj interface{}) (newMap map[string]interface{}, err error) {
    data, err := json.Marshal(obj)

    if err != nil {
        return
    }

    err = json.Unmarshal(data, &newMap) // Convert to a map
    return
}

Update 2: The User object looks like:

type User struct {
  gorm.Model
  Identity  string
  Birthday time.Time
  Phone string
  City string
  ...
  ActivityData         []Activity
}
1

There are 1 best solutions below

2
On

Looking, on gorm doc(https://gorm.io/docs/update.html), you can do something like this : Use the Updates instead of Update.

db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})

You can also use a db.Debug, to show the final query that gorm made, and see if matches with what are you expecting.