Skip to content

Commit

Permalink
Fix pointer marshal
Browse files Browse the repository at this point in the history
  • Loading branch information
alecsammon authored and mweibel committed Oct 3, 2024
1 parent dc3eac4 commit 3faa0cd
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
11 changes: 11 additions & 0 deletions sheriff.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,10 +282,21 @@ func marshalValue(options *Options, v reflect.Value) (interface{}, error) {
// types which are e.g. structs, slices or maps and implement one of the following interfaces should not be
// marshalled by sheriff because they'll be correctly marshalled by json.Marshal instead.
// Otherwise (e.g. net.IP) a byte slice may be output as a list of uints instead of as an IP string.
// This needs to be checked for both value and pointer types.
switch val.(type) {
case json.Marshaler, encoding.TextMarshaler, fmt.Stringer:
return val, nil
}

if v.CanAddr() {
addrVal := v.Addr().Interface()

switch addrVal.(type) {
case json.Marshaler, encoding.TextMarshaler, fmt.Stringer:
return addrVal, nil
}
}

k := v.Kind()

switch k {
Expand Down
41 changes: 38 additions & 3 deletions sheriff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package sheriff

import (
"encoding/json"
"fmt"
"net"
"reflect"
"testing"
Expand Down Expand Up @@ -579,14 +580,46 @@ type TestMarshal_Embedded struct {
Foo string `json:"foo" groups:"test"`
}

// TestMarshal_EmbeddedCustom is used to test an embedded struct with a custom marshaler that is not a pointer.
type TestMarshal_EmbeddedCustom struct {
Val int
Set bool
}

func (t TestMarshal_EmbeddedCustom) MarshalJSON() ([]byte, error) {
if t.Set {
return []byte(fmt.Sprintf("%d", t.Val)), nil
}

return nil, nil
}

// TestMarshal_EmbeddedCustomPtr is used to test an embedded struct with a custom marshaler that is a pointer.
type TestMarshal_EmbeddedCustomPtr struct {
Val int
Set bool
}

func (t *TestMarshal_EmbeddedCustomPtr) MarshalJSON() ([]byte, error) {
if t.Set {
return []byte(fmt.Sprintf("%d", t.Val)), nil
}

return nil, nil
}

type TestMarshal_EmbeddedParent struct {
*TestMarshal_Embedded
Bar string `json:"bar" groups:"test"`
*TestMarshal_EmbeddedCustom `json:"value"`
*TestMarshal_EmbeddedCustomPtr `json:"value_ptr"`
Bar string `json:"bar" groups:"test"`
}

func TestMarshal_EmbeddedField(t *testing.T) {
v := TestMarshal_EmbeddedParent{
&TestMarshal_Embedded{"Hello"},
&TestMarshal_EmbeddedCustom{10, true},
&TestMarshal_EmbeddedCustomPtr{20, true},
"World",
}
o := &Options{Groups: []string{"test"}}
Expand All @@ -598,8 +631,10 @@ func TestMarshal_EmbeddedField(t *testing.T) {
assert.NoError(t, err)

expected, err := json.Marshal(map[string]interface{}{
"bar": "World",
"foo": "Hello",
"bar": "World",
"foo": "Hello",
"value": 10,
"value_ptr": 20,
})
assert.NoError(t, err)

Expand Down

0 comments on commit 3faa0cd

Please sign in to comment.