GO: import a struct and rename it in json

805 Views Asked by At

I have built a database in go with gorm. For this I created a struct and with this struct I created a table. So far so good. In the backend everything works, but in the frontend the problem is that the JSON which is called always returns the ID in upper case and swagger generates me an ID which is lower case. Is there a way in Go that I can overwrite the imported struct from gorm with a JSON identifier?

import "gorm.io/gorm"

type Report struct {
   gorm.Model
   CreatedBy          User     `gorm:"foreignKey:CreatedByUserID" json:"createdBy"`
   Archived           bool     `json:"archived"`
}

This Struct gives me the following response

{
    "ID": 8,
    "CreatedAt": "2022-11-15T20:45:16.83+01:00",
    "UpdatedAt": "2022-12-27T21:34:17.871+01:00",
    "DeletedAt": null
    "createdBy": {
        "ID": 1,
        "CreatedAt": "2022-11-15T20:02:17.497+01:00",
        "UpdatedAt": "2022-11-15T20:02:17.497+01:00",
        ...
    },
    "archived": true,
}

Is there a way to make the ID lowercase (like Archived)? Or can I adjust it at swaggo so that it is generated in upper case.

What I have seen is that you can make the table without this gorm.Model and define all the attributes yourself. The problem is that I then have to create all the functionalities (delete, update, index, primary key, ...) of these columns myself.

2

There are 2 best solutions below

0
mattia_m On BEST ANSWER

I create my own gorm-model-struct:

type GormModel struct {
    ID        uint           `gorm:"primarykey" json:"id"`
    CreatedAt time.Time      `json:"createdAt"`
    UpdatedAt time.Time      `json:"updatedAt"`
    DeletedAt gorm.DeletedAt `gorm:"index" json:"deletedAt"`
} //@name models.gormModel

I import this struct into the other structs:

type Report struct {
   GormModel
   CreatedBy          User     `gorm:"foreignKey:CreatedByUserID" json:"createdBy"`
   Archived           bool     `json:"archived"`
}

Important is, that you add the json-key and set the attribute name.

3
Shalom Prinz On

You can use the mapstructure package.

mapstructure is a Go library for decoding generic map values to structures and vice versa

If you want to embed ID field from gorm.Model with custom json tag, and you want it to be on the same struct and not in a "substruct", you can use mapstructure:",squash" tag on the embedded model.

type Model struct {
    ID uint `json:"id"`
}

type Report struct {
    Model    `mapstructure:",squash"`
    Archived bool `json:"archived"`
}

func main() {
    input := map[string]interface{}{
        "id":       1,
        "archived": false,
    }

    var report Report
    if err := mapstructure.Decode(input, &report); err != nil {
        panic(err)
    }

    fmt.Println("Report ID:", report.ID)
    fmt.Println("Report ID via Model:", report.Model.ID)
}

As you can observe, with mapstructure.Decode method you can convert map to struct with the squash option, and you can then access ID of report directly. Note that you can still access report.Model and all its fields.

With mapstructure, you can make the ID lowercase as you wanted, and also accessable from the report struct directly, not only from a Model substruct.