icinga

Icinga2 API client in Go
git clone https://git.olowe.co/icinga
Log | Files | Refs | README | LICENSE

commit 46ca0f68f521c66d60a5d6646a0a15350533c9b8
parent f8031e6577708de406336a0d73dcb1bb922238bc
Author: Oliver Lowe <o@olowe.co>
Date:   Tue,  1 Feb 2022 13:14:39 +1100

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!

Diffstat:
Mhost.go | 42+++++++++++++-----------------------------
Mhost_test.go | 7+++----
Mresponse.go | 4++++
Mservice.go | 10+++++-----
Muser.go | 21++++++---------------
5 files changed, 31 insertions(+), 53 deletions(-)

diff --git a/host.go b/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}) } diff --git a/host_test.go b/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() } diff --git a/response.go b/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 } diff --git a/service.go b/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 { diff --git a/user.go b/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 {