Skip to content

Commit

Permalink
Remove omitempty in order to permit update with empty values (#233)
Browse files Browse the repository at this point in the history
  • Loading branch information
Galiley authored Dec 9, 2022
1 parent e8e203e commit 1e3d738
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 6 deletions.
36 changes: 30 additions & 6 deletions service_user.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package aiven

import (
"encoding/json"
"errors"
"fmt"
"reflect"
)

const (
Expand All @@ -23,12 +25,12 @@ type (
}

AccessControl struct {
M3Group *string `json:"m3_group,omitempty"`
RedisACLCategories []string `json:"redis_acl_categories,omitempty"`
RedisACLCommands []string `json:"redis_acl_commands,omitempty"`
RedisACLKeys []string `json:"redis_acl_keys,omitempty"`
RedisACLChannels []string `json:"redis_acl_channels,omitempty"`
PostgresAllowReplication *bool `json:"pg_allow_replication,omitempty"`
M3Group *string `json:"m3_group"`
RedisACLCategories []string `json:"redis_acl_categories"`
RedisACLCommands []string `json:"redis_acl_commands"`
RedisACLKeys []string `json:"redis_acl_keys"`
RedisACLChannels []string `json:"redis_acl_channels"`
PostgresAllowReplication *bool `json:"pg_allow_replication"`
}

// ServiceUsersHandler is the client that interacts with the ServiceUsers
Expand Down Expand Up @@ -59,6 +61,28 @@ type (
}
)

// MarshalJSON implements a custom marshalling process for AccessControl where only null fields are omitted
func (ac AccessControl) MarshalJSON() ([]byte, error) {
out := make(map[string]interface{})

fields := reflect.TypeOf(ac)
values := reflect.ValueOf(ac)

for i := 0; i < fields.NumField(); i++ {
field := fields.Field(i)
value := values.Field(i)

switch value.Kind() {
case reflect.Pointer, reflect.Slice: // *string, *bool, []string
if !value.IsNil() {
jsonName := field.Tag.Get("json")
out[jsonName] = value.Interface()
}
}
}
return json.Marshal(out)
}

// Create creates the given User on Aiven.
func (h *ServiceUsersHandler) Create(project, service string, req CreateServiceUserRequest) (*ServiceUser, error) {
path := buildPath("project", project, "service", service, "user")
Expand Down
63 changes: 63 additions & 0 deletions service_user_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package aiven

import (
"bytes"
"encoding/json"
"reflect"
"testing"
)

// TestAccessControlMarshalJSON test AccessControl JSON marshalling process
func TestAccessControlMarshalJSON(t *testing.T) {
strPtr := func(s string) *string {
return &s
}
type notEmpty struct {
M3Group string `json:"m3_group"`
RedisACLKeys []string `json:"redis_acl_keys"`
}

tests := []struct {
name string
input *AccessControl
wantType interface{}
want interface{}
}{
{
name: "empty",
input: &AccessControl{},
wantType: &map[string]interface{}{},
want: &map[string]interface{}{},
},
{
name: "notempty",
input: &AccessControl{
M3Group: strPtr("foo"),
RedisACLKeys: []string{"bar"},
},
wantType: &notEmpty{},
want: &notEmpty{
M3Group: "foo",
RedisACLKeys: []string{"bar"},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
b, err := json.Marshal(tt.input)
if err != nil {
t.Errorf("MarshalJSON() error = %v", err)
return
}

dec := json.NewDecoder(bytes.NewReader(b))
dec.DisallowUnknownFields()
if err := dec.Decode(tt.wantType); err != nil {
t.Errorf("Decode() error = %v", err)
}
if !reflect.DeepEqual(tt.wantType, tt.want) {
t.Errorf("DeepEqual() got = %+v, want = %+v", tt.wantType, tt.want)
}
})
}
}

0 comments on commit 1e3d738

Please sign in to comment.