I currently have a struct model where I declare a many-to-many relationship between two tables: StructA and StructB. StructB has a list of StructA, and this association has its own attribute.
// My current model
type StructA struct {
ID uint `json:"id" gorm:"primaryKey"`
PropA string `json:"propA"`
}
type StructB struct {
ID uint `json:"id" gorm:"primaryKey"`
ListStructA []JoinTable `json:"listStructA"`
}
type JoinTable struct {
StructAID uint `json:"-" gorm:"primaryKey"`
StructBID uint `json:"-" gorm:"primaryKey"`
StructA StructA `json:"structA"`
JoinProp int `json:"joinProp"`
}
And the marshalling of StructB produces this kind of result
// Current StructB json
{
"id": 1,
"listStructA": [
{
"joinProp": 1,
"structA": {
"id": 1,
"propA": "some prop"
}
}
]
}
With this implementation, my database model is efficient. But I would like to have all attributes in the listStructA objects at the same hierarchical level, because it is quite obvious for the consumer of this json that this part of the data contains structB attributes, and it would feel off-putting to type structB.listStructA[0].structA.propA instead of structB.listStructA[0].propA. So my end goal is to have this structure when marshalling structB.
// Wanted StructB json
{
"id": 1,
"listStructA": [
{
"id": 1,
"propA": "some prop",
"joinProp": 1,
}
]
}
I also point out that in the application logic, it makes sense to type structB.listStructA[0].joinProp, but not store JoinProp in StructA
One obvious way to do it, is to make the StructA attribute from the JoinTable as an embedded struct
type JoinTable struct {
StructA
StructBID uint `json:"-" gorm:"primaryKey"`
JoinProp int `json:"joinProp"`
}
But this will duplicate the data of StructA in JoinTable's database table, instead of referencing it (ruining the database model). The only thing about embedded struct I was able to find in the official documentation is in this section, but it explains how to do the exact opposite (having embedded struct in database but not in code).
So is there something prebuilt in GORM to have best of both world? Or does this require an implementation I overlooked?
I can always implement the MarshalJSON method to JoinTable in last resort, but I would prefer not to do it if there is a smarter way of thing.