commit 46ca0f68f521c66d60a5d6646a0a15350533c9b8 from: Oliver Lowe date: Tue Feb 1 02:14:39 2022 UTC Marshal using struct tags rather than a custom map I was excluding some struct fields so I thought I'd need to do some custom marshalling . But you don't need to do this as you can use struct tags to optionally exclude things from being put into JSON. Now there's no longer duplicate code between struct tags and keys in a map when marshalling. Handy! commit - f8031e6577708de406336a0d73dcb1bb922238bc commit + 46ca0f68f521c66d60a5d6646a0a15350533c9b8 blob - 94490ea828a33c5e3bf0357e49e8ad88408bec62 blob + b9c107d451f578dab92dc014b6f35ec92d069336 --- host.go +++ host.go @@ -5,19 +5,19 @@ import "encoding/json" // Host represents a Host object. To create a Host, the Name and CheckCommand // fields must be set. type Host struct { - Name string `json:"name"` + Name string `json:"-"` Address string `json:"address"` Address6 string `json:"address6"` - Groups []string `json:"groups"` - State HostState `json:"state"` - StateType StateType `json:"state_type"` + Groups []string `json:"groups,omitempty"` + State HostState `json:"state,omitempty"` + StateType StateType `json:"state_type,omitempty"` CheckCommand string `json:"check_command"` - DisplayName string `json:"display_name"` - Acknowledgement bool + DisplayName string `json:"display_name,omitempty"` + Acknowledgement bool `json:",omitempty"` } type HostGroup struct { - Name string `json:"name"` + Name string `json:"-"` DisplayName string `json:"display_name"` } @@ -58,17 +58,9 @@ func (hg HostGroup) path() string { } func (h Host) MarshalJSON() ([]byte, error) { - attrs := make(map[string]interface{}) - attrs["address"] = h.Address - attrs["address6"] = h.Address6 - if len(h.Groups) > 0 { - attrs["groups"] = h.Groups - } - attrs["check_command"] = h.CheckCommand - attrs["display_name"] = h.DisplayName - m := make(map[string]interface{}) - m["attrs"] = attrs - return json.Marshal(m) + type alias Host + a := alias(h) + return json.Marshal(map[string]interface{}{"attrs": a}) } // UnmarhsalJSON unmarshals host attributes into more meaningful Host field types. @@ -90,15 +82,7 @@ func (h *Host) UnmarshalJSON(data []byte) error { } func (hg HostGroup) MarshalJSON() ([]byte, error) { - type attrs struct { - DisplayName string `json:"display_name"` - } - type group struct { - Attrs attrs `json:"attrs"` - } - return json.Marshal(&group{ - Attrs: attrs{ - DisplayName: hg.DisplayName, - }, - }) + type alias HostGroup + a := alias(hg) + return json.Marshal(map[string]interface{}{"attrs": a}) } blob - 509bcdc19a2f9c3bf4251153eae6b2788452af53 blob + 158940542dafee9f573ab77e19866a464b348d17 --- host_test.go +++ host_test.go @@ -8,9 +8,9 @@ import ( ) func TestHostMarshal(t *testing.T) { - s := `{"attrs":{"address":"192.0.2.1","address6":"2001:db8::","groups":["test"],"check_command":"dummy","display_name":"Example host"}}` + b := []byte(`{"attrs":{"address":"192.0.2.1","address6":"2001:db8::","check_command":"dummy","display_name":"Example host","groups":["test"]}}`) want := make(map[string]interface{}) - if err := json.Unmarshal([]byte(s), &want); err != nil { + if err := json.Unmarshal(b, &want); err != nil { t.Fatal(err) } @@ -19,7 +19,6 @@ func TestHostMarshal(t *testing.T) { Address: "192.0.2.1", Address6: "2001:db8::", Groups: []string{"test"}, - State: HostDown, StateType: StateSoft, CheckCommand: "dummy", DisplayName: "Example host", @@ -27,11 +26,11 @@ func TestHostMarshal(t *testing.T) { if err != nil { t.Fatal(err) } + t.Log(string(p)) got := make(map[string]interface{}) if err := json.Unmarshal(p, &got); err != nil { t.Fatal(err) } - if !reflect.DeepEqual(want, got) { t.Fail() } blob - f80e37d055df98e1df88ffe8fd5fb1f9d518b6e0 blob + c2a79861f1e2ae314c22000331bd19aef8938768 --- response.go +++ response.go @@ -56,24 +56,28 @@ func parseResponse(r io.Reader) (*response, error) { switch r.Type { case "Host": var h Host + h.Name = r.Name if err := json.Unmarshal(r.Attrs, &h); err != nil { return nil, err } resp.Results = append(resp.Results, h) case "Service": var s Service + s.Name = r.Name if err := json.Unmarshal(r.Attrs, &s); err != nil { return nil, err } resp.Results = append(resp.Results, s) case "User": var u User + u.Name = r.Name if err := json.Unmarshal(r.Attrs, &u); err != nil { return nil, err } resp.Results = append(resp.Results, u) case "HostGroup": var h HostGroup + h.Name = r.Name if err := json.Unmarshal(r.Attrs, &h); err != nil { return nil, err } blob - 80355e873fde10b9bfc9c2dbb9447ffd185142a1 blob + 4affd0ebef13449176ad6412031ea66e8d13b778 --- service.go +++ service.go @@ -12,14 +12,14 @@ func (s Service) path() string { // Service represents a Service object. type Service struct { - Name string `json:"__name"` - Groups []string + Name string `json:"-"` + Groups []string `json:"groups,omitempty"` State ServiceState StateType StateType `json:"state_type"` CheckCommand string `json:"check_command"` - DisplayName string `json:"display_name"` - LastCheckResult CheckResult `json:"last_check_result"` - Acknowledgement bool + DisplayName string `json:"display_name,omitempty"` + LastCheckResult CheckResult `json:"last_check_result,omitempty"` + Acknowledgement bool `json:",omitempty"` } type CheckResult struct { blob - d53ca084c2e18c3b56dc38d0e727c36e48fef4a5 blob + 740b452988d7f0b545fbfb14b7880844d4cf5edb --- user.go +++ user.go @@ -5,24 +5,15 @@ import "encoding/json" // User represents a User object. // Note that this is different from an ApiUser. type User struct { - Name string - Email string - Groups []string + Name string `json:"-"` + Email string `json:"email,omitempty"` + Groups []string `json:"groups,omitempty"` } func (u User) MarshalJSON() ([]byte, error) { - type attrs struct { - Email string `json:"email"` - Groups []string `json:"groups,omitempty"` - } - return json.Marshal(&struct { - Attrs attrs `json:"attrs"` - }{ - Attrs: attrs{ - Email: u.Email, - Groups: u.Groups, - }, - }) + type alias User + a := alias(u) + return json.Marshal(map[string]interface{}{"attrs": a}) } func (u User) name() string {