Skip to content

Commit

Permalink
Merge pull request #218 from Yamashou/fix-bug-marshal
Browse files Browse the repository at this point in the history
Fix MarsahlJson
  • Loading branch information
Yamashou authored Apr 22, 2024
2 parents 5eec23e + 3ebcb86 commit bfc7c4f
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 10 deletions.
35 changes: 25 additions & 10 deletions clientv2/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,8 @@ func MarshalJSON(v interface{}) ([]byte, error) {
}

// getTypeEncoder returns an appropriate encoder function for the provided type.
func getTypeEncoder(t reflect.Type) func(a any) ([]byte, error) {
if t.Implements(reflect.TypeOf((*graphql.Marshaler)(nil)).Elem()) {
func getTypeEncoder(t reflect.Type) func(any2 any) ([]byte, error) {
if t.Implements(reflect.TypeOf((*graphql.Marshaler)(nil)).Elem()) || (t.Kind() == reflect.Ptr && reflect.PtrTo(t).Implements(reflect.TypeOf((*graphql.Marshaler)(nil)).Elem())) {
return gqlMarshalerEncoder
}

Expand Down Expand Up @@ -444,7 +444,7 @@ func getTypeEncoder(t reflect.Type) func(a any) ([]byte, error) {
}
}

func gqlMarshalerEncoder(v interface{}) ([]byte, error) {
func gqlMarshalerEncoder(v any) ([]byte, error) {
var buf bytes.Buffer
if val, ok := v.(graphql.Marshaler); ok {
val.MarshalGQL(&buf)
Expand Down Expand Up @@ -546,19 +546,34 @@ func checkMarshalerFields(t reflect.Type) bool {
if checkMarshalerFields(f.Type) {
return true
}

// If the value type is interface{}, we need to handle it at runtime
if f.Type.Kind() == reflect.Interface {
return true // Assume it could implement Marshaler at runtime
}
}

case reflect.Map:
// Check both key and value types for Marshaler implementation; usually, value type is what matters
keyType, valueType := t.Key(), t.Elem()
if isMarshalerType(valueType) || isMarshalerType(keyType) {
// Check key type for Marshaler implementation (usually not needed unless custom types used as keys)
keyType := t.Key()
if isMarshalerType(keyType) {
return true
}
// Recursively check the map value type
if checkMarshalerFields(valueType) {

// Check value type for Marshaler implementation
valueType := t.Elem()
if isMarshalerType(valueType) {
return true
}

// If the value type is interface{}, we need to handle it at runtime
if valueType.Kind() == reflect.Interface {
return true // Assume it could implement Marshaler at runtime
}

// Recursively check the map value type
return checkMarshalerFields(valueType)

case reflect.Slice, reflect.Array:
// Recursively check the element type
return checkMarshalerFields(t.Elem())
Expand All @@ -581,7 +596,7 @@ func isMarshalerType(t reflect.Type) bool {
return false
}

func newStructEncoder(t reflect.Type) func(interface{}) ([]byte, error) {
func newStructEncoder(t reflect.Type) func(any2 any) ([]byte, error) {
fields := prepareFields(t)
marshalerFieldExists := checkMarshalerFields(t)

Expand Down Expand Up @@ -619,7 +634,6 @@ func trimQuotes(s string) string {

func newMapEncoder(t reflect.Type) func(interface{}) ([]byte, error) {
keyEncoder := getTypeEncoder(t.Key())
valueEncoder := getTypeEncoder(t.Elem())

return func(v interface{}) ([]byte, error) {
val := reflect.ValueOf(v)
Expand All @@ -633,6 +647,7 @@ func newMapEncoder(t reflect.Type) func(interface{}) ([]byte, error) {
keyStr = trimQuotes(keyStr)

value := val.MapIndex(key)
valueEncoder := getTypeEncoder(value.Type())
encodedValue, err := valueEncoder(value.Interface())
if err != nil {
return nil, err
Expand Down
20 changes: 20 additions & 0 deletions clientv2/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,26 @@ func TestMarshalJSON(t *testing.T) {
want []byte
wantErr bool
}{
{
name: "marshal NumberOne",
args: args{
v: map[string]interface{}{"input": NumberOne},
},
want: []byte(`{"input":"ONE"}`),
},
{
name: "marshal NumberTwo",
args: args{
v: Request{
OperationName: "query",
Query: `query ($input: Number!) { input }`,
Variables: map[string]any{
"input": NumberTwo,
},
},
},
want: []byte(`{"operationName":"query", "query":"query ($input: Number!) { input }","variables":{"input":"TWO"}}`),
},
{
name: "marshal a struct with custom marshaler",
args: args{
Expand Down

0 comments on commit bfc7c4f

Please sign in to comment.