diff --git a/encode_test.go b/encode_test.go index 59bb08ff..1c0de3cc 100644 --- a/encode_test.go +++ b/encode_test.go @@ -2406,3 +2406,21 @@ func TestIssue339(t *testing.T) { t.Errorf("unexpected result: %v != %v", got, expected) } } + +func TestIssue376(t *testing.T) { + type Container struct { + V interface{} `json:"value"` + } + type MapOnly struct { + Map map[string]int64 `json:"map"` + } + b, err := json.Marshal(Container{MapOnly{}}) + if err != nil { + t.Fatal(err) + } + got := string(b) + expected := `{"value":{"map":null}}` + if got != expected { + t.Errorf("unexpected result: %v != %v", got, expected) + } +} diff --git a/internal/cmd/generator/vm.go.tmpl b/internal/cmd/generator/vm.go.tmpl index 91b11e1f..645d20f9 100644 --- a/internal/cmd/generator/vm.go.tmpl +++ b/internal/cmd/generator/vm.go.tmpl @@ -3,6 +3,7 @@ package vm import ( "math" + "reflect" "sort" "unsafe" @@ -194,9 +195,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b typ = iface.typ } if ifacePtr == nil { - b = appendNullComma(ctx, b) - code = code.Next - break + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) diff --git a/internal/encoder/vm/vm.go b/internal/encoder/vm/vm.go index 91b11e1f..645d20f9 100644 --- a/internal/encoder/vm/vm.go +++ b/internal/encoder/vm/vm.go @@ -3,6 +3,7 @@ package vm import ( "math" + "reflect" "sort" "unsafe" @@ -194,9 +195,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b typ = iface.typ } if ifacePtr == nil { - b = appendNullComma(ctx, b) - code = code.Next - break + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) diff --git a/internal/encoder/vm_color/vm.go b/internal/encoder/vm_color/vm.go index 5c6c52c3..a63e83e5 100644 --- a/internal/encoder/vm_color/vm.go +++ b/internal/encoder/vm_color/vm.go @@ -3,6 +3,7 @@ package vm_color import ( "math" + "reflect" "sort" "unsafe" @@ -194,9 +195,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b typ = iface.typ } if ifacePtr == nil { - b = appendNullComma(ctx, b) - code = code.Next - break + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) diff --git a/internal/encoder/vm_color_indent/vm.go b/internal/encoder/vm_color_indent/vm.go index 42dc11ca..3b4e22e5 100644 --- a/internal/encoder/vm_color_indent/vm.go +++ b/internal/encoder/vm_color_indent/vm.go @@ -3,6 +3,7 @@ package vm_color_indent import ( "math" + "reflect" "sort" "unsafe" @@ -194,9 +195,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b typ = iface.typ } if ifacePtr == nil { - b = appendNullComma(ctx, b) - code = code.Next - break + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ))) diff --git a/internal/encoder/vm_indent/vm.go b/internal/encoder/vm_indent/vm.go index dfe0cc64..836c5c8a 100644 --- a/internal/encoder/vm_indent/vm.go +++ b/internal/encoder/vm_indent/vm.go @@ -3,6 +3,7 @@ package vm_indent import ( "math" + "reflect" "sort" "unsafe" @@ -194,9 +195,12 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b typ = iface.typ } if ifacePtr == nil { - b = appendNullComma(ctx, b) - code = code.Next - break + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if !isDirectedNil { + b = appendNullComma(ctx, b) + code = code.Next + break + } } ctx.KeepRefs = append(ctx.KeepRefs, up) ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ)))