From 3d8cfaf0445ac3b3fead855621687f2ccf0131c5 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Wed, 14 Sep 2022 11:34:48 +0300 Subject: [PATCH] Move MarshalAndDeleteEmpty to util --- responses.go | 28 +++++----------------------- util/marshal.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 23 deletions(-) create mode 100644 util/marshal.go diff --git a/responses.go b/responses.go index 3e25b918..14b4a6cd 100644 --- a/responses.go +++ b/responses.go @@ -3,16 +3,15 @@ package mautrix import ( "bytes" "encoding/json" - "fmt" "reflect" "strconv" "strings" "github.com/tidwall/gjson" - "github.com/tidwall/sjson" "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/id" + "maunium.net/go/mautrix/util" ) // RespWhoami is the JSON response for https://spec.matrix.org/v1.2/client-server-api/#get_matrixclientv3accountwhoami @@ -252,25 +251,8 @@ type marshalableRespSync RespSync var syncPathsToDelete = []string{"account_data", "presence", "to_device", "device_lists", "device_one_time_keys_count", "rooms"} -func marshalAndDeleteEmpty(marshalable interface{}, paths []string) ([]byte, error) { - data, err := json.Marshal(marshalable) - if err != nil { - return nil, err - } - for _, path := range paths { - res := gjson.GetBytes(data, path) - if res.IsObject() && len(res.Raw) == 2 { - data, err = sjson.DeleteBytes(data, path) - if err != nil { - return nil, fmt.Errorf("failed to delete empty %s: %w", path, err) - } - } - } - return data, nil -} - func (rs *RespSync) MarshalJSON() ([]byte, error) { - return marshalAndDeleteEmpty((*marshalableRespSync)(rs), syncPathsToDelete) + return util.MarshalAndDeleteEmpty((*marshalableRespSync)(rs), syncPathsToDelete) } type DeviceLists struct { @@ -298,7 +280,7 @@ type marshalableSyncLeftRoom SyncLeftRoom var syncLeftRoomPathsToDelete = []string{"summary", "state", "timeline"} func (slr SyncLeftRoom) MarshalJSON() ([]byte, error) { - return marshalAndDeleteEmpty((marshalableSyncLeftRoom)(slr), syncLeftRoomPathsToDelete) + return util.MarshalAndDeleteEmpty((marshalableSyncLeftRoom)(slr), syncLeftRoomPathsToDelete) } type SyncJoinedRoom struct { @@ -323,7 +305,7 @@ type marshalableSyncJoinedRoom SyncJoinedRoom var syncJoinedRoomPathsToDelete = []string{"summary", "state", "timeline", "ephemeral", "account_data"} func (sjr SyncJoinedRoom) MarshalJSON() ([]byte, error) { - return marshalAndDeleteEmpty((marshalableSyncJoinedRoom)(sjr), syncJoinedRoomPathsToDelete) + return util.MarshalAndDeleteEmpty((marshalableSyncJoinedRoom)(sjr), syncJoinedRoomPathsToDelete) } type SyncInvitedRoom struct { @@ -336,7 +318,7 @@ type marshalableSyncInvitedRoom SyncInvitedRoom var syncInvitedRoomPathsToDelete = []string{"summary"} func (sir SyncInvitedRoom) MarshalJSON() ([]byte, error) { - return marshalAndDeleteEmpty((marshalableSyncInvitedRoom)(sir), syncInvitedRoomPathsToDelete) + return util.MarshalAndDeleteEmpty((marshalableSyncInvitedRoom)(sir), syncInvitedRoomPathsToDelete) } type RespTurnServer struct { diff --git a/util/marshal.go b/util/marshal.go new file mode 100644 index 00000000..180adef2 --- /dev/null +++ b/util/marshal.go @@ -0,0 +1,30 @@ +package util + +import ( + "encoding/json" + "fmt" + + "github.com/tidwall/gjson" + "github.com/tidwall/sjson" +) + +// MarshalAndDeleteEmpty marshals a JSON object, then uses gjson to delete empty objects at the given gjson paths. +// +// This can be used as a convenient way to create a marshaler that omits empty non-pointer structs. +// See mautrix.RespSync for example. +func MarshalAndDeleteEmpty(marshalable interface{}, paths []string) ([]byte, error) { + data, err := json.Marshal(marshalable) + if err != nil { + return nil, err + } + for _, path := range paths { + res := gjson.GetBytes(data, path) + if res.IsObject() && len(res.Raw) == 2 { + data, err = sjson.DeleteBytes(data, path) + if err != nil { + return nil, fmt.Errorf("failed to delete empty %s: %w", path, err) + } + } + } + return data, nil +}