From ac9a7dd8e30a998880b16813b7f23409c256e737 Mon Sep 17 00:00:00 2001 From: peterlimg Date: Tue, 20 Jul 2021 23:14:26 +1000 Subject: [PATCH 1/4] Fix encode issue for embed struct with tag --- encode_test.go | 53 ++++++++++++++++++++++++++ internal/cmd/generator/vm.go.tmpl | 6 ++- internal/encoder/vm/vm.go | 6 ++- internal/encoder/vm_color/vm.go | 6 ++- internal/encoder/vm_color_indent/vm.go | 6 ++- internal/encoder/vm_indent/vm.go | 6 ++- 6 files changed, 73 insertions(+), 10 deletions(-) diff --git a/encode_test.go b/encode_test.go index 5b271b0..98f71b0 100644 --- a/encode_test.go +++ b/encode_test.go @@ -191,6 +191,59 @@ func Test_Marshal(t *testing.T) { }) }) }) + + t.Run("embedded with tag", func(t *testing.T) { + type T struct { + A string `json:"a"` + } + type U struct { + *T `json:"t"` + B string `json:"b"` + } + type T2 struct { + A string `json:"a,omitempty"` + } + type U2 struct { + *T2 `json:"t,omitempty"` + B string `json:"b,omitempty"` + } + t.Run("exists field", func(t *testing.T) { + bytes, err := json.Marshal(&U{ + T: &T{ + A: "aaa", + }, + B: "bbb", + }) + assertErr(t, err) + assertEq(t, "embedded", `{"t":{"a":"aaa"},"b":"bbb"}`, string(bytes)) + t.Run("omitempty", func(t *testing.T) { + bytes, err := json.Marshal(&U2{ + T2: &T2{ + A: "aaa", + }, + B: "bbb", + }) + assertErr(t, err) + assertEq(t, "embedded", `{"t":{"a":"aaa"},"b":"bbb"}`, string(bytes)) + }) + }) + + t.Run("none field", func(t *testing.T) { + bytes, err := json.Marshal(&U{ + B: "bbb", + }) + assertErr(t, err) + assertEq(t, "embedded", `{"t":null,"b":"bbb"}`, string(bytes)) + t.Run("omitempty", func(t *testing.T) { + bytes, err := json.Marshal(&U2{ + B: "bbb", + }) + assertErr(t, err) + assertEq(t, "embedded", `{"b":"bbb"}`, string(bytes)) + }) + }) + }) + t.Run("omitempty", func(t *testing.T) { type T struct { A int `json:",omitempty"` diff --git a/internal/cmd/generator/vm.go.tmpl b/internal/cmd/generator/vm.go.tmpl index 78da5e4..f2c992a 100644 --- a/internal/cmd/generator/vm.go.tmpl +++ b/internal/cmd/generator/vm.go.tmpl @@ -578,8 +578,10 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } - if (code.Flags&encoder.AnonymousKeyFlags) == 0 && len(code.Key) > 0 { - b = appendStructKey(ctx, code, b) + if len(code.Key) > 0 { + if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } } p += uintptr(code.Offset) code = code.Next diff --git a/internal/encoder/vm/vm.go b/internal/encoder/vm/vm.go index 78da5e4..f2c992a 100644 --- a/internal/encoder/vm/vm.go +++ b/internal/encoder/vm/vm.go @@ -578,8 +578,10 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } - if (code.Flags&encoder.AnonymousKeyFlags) == 0 && len(code.Key) > 0 { - b = appendStructKey(ctx, code, b) + if len(code.Key) > 0 { + if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } } p += uintptr(code.Offset) code = code.Next diff --git a/internal/encoder/vm_color/vm.go b/internal/encoder/vm_color/vm.go index 0d4c472..70de3e7 100644 --- a/internal/encoder/vm_color/vm.go +++ b/internal/encoder/vm_color/vm.go @@ -578,8 +578,10 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } - if (code.Flags&encoder.AnonymousKeyFlags) == 0 && len(code.Key) > 0 { - b = appendStructKey(ctx, code, b) + if len(code.Key) > 0 { + if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } } p += uintptr(code.Offset) code = code.Next diff --git a/internal/encoder/vm_color_indent/vm.go b/internal/encoder/vm_color_indent/vm.go index de8b858..2d014e5 100644 --- a/internal/encoder/vm_color_indent/vm.go +++ b/internal/encoder/vm_color_indent/vm.go @@ -578,8 +578,10 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } - if (code.Flags&encoder.AnonymousKeyFlags) == 0 && len(code.Key) > 0 { - b = appendStructKey(ctx, code, b) + if len(code.Key) > 0 { + if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } } p += uintptr(code.Offset) code = code.Next diff --git a/internal/encoder/vm_indent/vm.go b/internal/encoder/vm_indent/vm.go index d10ce75..25d2ebc 100644 --- a/internal/encoder/vm_indent/vm.go +++ b/internal/encoder/vm_indent/vm.go @@ -578,8 +578,10 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b if code.Flags&encoder.AnonymousHeadFlags == 0 { b = appendStructHead(ctx, b) } - if (code.Flags&encoder.AnonymousKeyFlags) == 0 && len(code.Key) > 0 { - b = appendStructKey(ctx, code, b) + if len(code.Key) > 0 { + if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 { + b = appendStructKey(ctx, code, b) + } } p += uintptr(code.Offset) code = code.Next From a95c5abe6cdde71713def20d7a7de8a8d866bce8 Mon Sep 17 00:00:00 2001 From: peterlimg Date: Thu, 22 Jul 2021 14:54:11 +1000 Subject: [PATCH 2/4] Fix indent issue for embed struct with tag --- internal/encoder/compiler.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/encoder/compiler.go b/internal/encoder/compiler.go index 01a5d4b..a18ab4d 100644 --- a/internal/encoder/compiler.go +++ b/internal/encoder/compiler.go @@ -1425,7 +1425,10 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) { for k, v := range anonymousStructFieldPairMap(tags, tagKey, valueCode) { anonymousFields[k] = append(anonymousFields[k], v...) } - valueCode.decIndent() + + if !tag.IsTaggedKey { + valueCode.decIndent() + } // fix issue144 if !(isPtr && strings.Contains(valueCode.Op.String(), "Marshal")) { From ad245e532349d28b461a8e0faa3119e118df51c3 Mon Sep 17 00:00:00 2001 From: peterlimg Date: Thu, 22 Jul 2021 17:22:07 +1000 Subject: [PATCH 3/4] Fix incorrect indent --- internal/encoder/compiler.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/internal/encoder/compiler.go b/internal/encoder/compiler.go index a18ab4d..84e4f91 100644 --- a/internal/encoder/compiler.go +++ b/internal/encoder/compiler.go @@ -1417,7 +1417,7 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) { valueCode = code } - if field.Anonymous { + if field.Anonymous && !tag.IsTaggedKey { tagKey := "" if tag.IsTaggedKey { tagKey = tag.Key @@ -1426,9 +1426,7 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) { anonymousFields[k] = append(anonymousFields[k], v...) } - if !tag.IsTaggedKey { - valueCode.decIndent() - } + valueCode.decIndent() // fix issue144 if !(isPtr && strings.Contains(valueCode.Op.String(), "Marshal")) { From 91e691adc57ca4fec80076b20672ed44ecb1c2a9 Mon Sep 17 00:00:00 2001 From: peterlimg Date: Tue, 27 Jul 2021 21:53:59 +1000 Subject: [PATCH 4/4] Fix decodeEscapeString err `p` was not updated after the `stream.buf` is reallocated --- internal/decoder/string.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/decoder/string.go b/internal/decoder/string.go index 1e1ce15..5b1a00b 100644 --- a/internal/decoder/string.go +++ b/internal/decoder/string.go @@ -170,6 +170,7 @@ RETRY: s.buf = append(s.buf[:s.cursor-1], s.buf[s.cursor:]...) s.length-- s.cursor-- + p = s.bufptr() return p, nil }