From c8d6da88dd5e417e57d7125bb805874f78496fcd Mon Sep 17 00:00:00 2001 From: Nao Yonashiro Date: Sun, 3 Jul 2022 06:05:26 +0900 Subject: [PATCH] fix: confusing nil in direct interface with typed nil fix #376 --- encode_test.go | 18 ++++++++++++++++++ internal/cmd/generator/vm.go.tmpl | 4 +++- internal/encoder/vm/vm.go | 4 +++- internal/encoder/vm_color/vm.go | 4 +++- internal/encoder/vm_color_indent/vm.go | 4 +++- internal/encoder/vm_indent/vm.go | 4 +++- 6 files changed, 33 insertions(+), 5 deletions(-) diff --git a/encode_test.go b/encode_test.go index 59bb08f..1c0de3c 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 91b11e1..cb4db57 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" @@ -193,7 +194,8 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if ifacePtr == nil && !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break diff --git a/internal/encoder/vm/vm.go b/internal/encoder/vm/vm.go index 91b11e1..cb4db57 100644 --- a/internal/encoder/vm/vm.go +++ b/internal/encoder/vm/vm.go @@ -3,6 +3,7 @@ package vm import ( "math" + "reflect" "sort" "unsafe" @@ -193,7 +194,8 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if ifacePtr == nil && !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break diff --git a/internal/encoder/vm_color/vm.go b/internal/encoder/vm_color/vm.go index 5c6c52c..e8a5597 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" @@ -193,7 +194,8 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if ifacePtr == nil && !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break diff --git a/internal/encoder/vm_color_indent/vm.go b/internal/encoder/vm_color_indent/vm.go index 42dc11c..79cfdd8 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" @@ -193,7 +194,8 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if ifacePtr == nil && !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break diff --git a/internal/encoder/vm_indent/vm.go b/internal/encoder/vm_indent/vm.go index dfe0cc6..5451484 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" @@ -193,7 +194,8 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b ifacePtr = iface.ptr typ = iface.typ } - if ifacePtr == nil { + isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ) + if ifacePtr == nil && !isDirectedNil { b = appendNullComma(ctx, b) code = code.Next break