2

I use GORM as ORM library for my project (REST API).

A single book has an author. When no author is defined (no first name or last name), I want to omit the complete author field.

Now, the JSON output of the "author" field is "author": {}, instead of omitting the field.

What could be a clean solution to achieve this?

Code snippet

type Author struct {
    FirstName string `json:"first_name,omitempty"`
    LastName  int32  `json:"last_name,omitempty"`
}

type Book struct {
    ID          uint
    Title       string      `gorm:"index;not null" json:"title"`
    Author      Author      `gorm:"embedded" json:"author,omitempty"`
    CreatedAt   time.Time   `json:"created_at"`
    UpdatedAt   time.Time   `json:"updated_at"`
}
studio-pj
  • 689
  • 6
  • 19
  • you should get what you want if you change `Author Author` to `Author *Author`. https://stackoverflow.com/questions/18088294/how-to-not-marshal-an-empty-struct-into-json-with-go – Emin Laletovic Dec 06 '22 at 21:13

1 Answers1

1

Since it looks like GORM will (always populate an embedded struct)(https://github.com/go-gorm/gorm/issues/5431), I don't know that changing it to a pointer will work (although that would be a good first attempt, it might).

Assuming it doesn't, you can create basically two versions of the struct, and switch to the one which uses a pointer when encoding to json, and omit if empty:

type book struct {
  ID        uint
  Title     string    `gorm:"index;not null" json:"title"`
  CreatedAt time.Time `json:"created_at"`
  UpdatedAt time.Time `json:"updated_at"`
}

type Book struct {
  book
  Author Author `gorm:"embedded" json:"-"`
}


type JSONBook struct {
  book
  Author *Author `json:"author,omitempty"`
}

func (b Book) MarshalJSON() ([]byte, error) {
  jb := JSONBook{book: b.book}
  if b.Author.FirstName != "" || b.Author.LastName != 0 {
    jb.Author = &b.Author
  }
  return json.Marshal(jb)
}

https://go.dev/play/p/K905LVhCff6

dave
  • 62,300
  • 5
  • 72
  • 93