Skip to content

Commit 691af6c

Browse files
dsnetgopherbot
authored andcommitted
encoding/json: fix Indent trailing whitespace regression in goexperiment.jsonv2
The Indent function preserves trailing whitespace, while the v1 emulation under v2 implementation accidentally dropped it. There was prior logic that attempted to preserve it, but it did not work correctly since it ran in a defer and accidentally mutated the dst input argument rather than the output argument. Move the logic to the end and avoid a defer. Also, add a test to both v1 and v1in2 to codify this behavior. This only modifies code that is compiled in under goexperiment.jsonv2. Updates golang#13520 Fixes golang#74806 Change-Id: I22b1a8da5185eb969e2a8a111b625d3752cfcbe8 Reviewed-on: https://go-review.googlesource.com/c/go/+/692195 Reviewed-by: Sean Liao <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> Reviewed-by: David Chase <[email protected]> Auto-Submit: Sean Liao <[email protected]>
1 parent 925149d commit 691af6c

File tree

3 files changed

+10
-12
lines changed

3 files changed

+10
-12
lines changed

src/encoding/json/scanner_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ func TestCompactAndIndent(t *testing.T) {
7474
-5e+2
7575
]`},
7676
{Name(""), "{\"\":\"<>&\u2028\u2029\"}", "{\n\t\"\": \"<>&\u2028\u2029\"\n}"}, // See golang.org/issue/34070
77+
{Name(""), `null`, "null \n\r\t"}, // See golang.org/issue/13520 and golang.org/issue/74806
7778
}
7879
var buf bytes.Buffer
7980
for _, tt := range tests {
@@ -102,7 +103,7 @@ func TestCompactAndIndent(t *testing.T) {
102103
buf.Reset()
103104
if err := Indent(&buf, []byte(tt.compact), "", "\t"); err != nil {
104105
t.Errorf("%s: Indent error: %v", tt.Where, err)
105-
} else if got := buf.String(); got != tt.indent {
106+
} else if got := buf.String(); got != strings.TrimRight(tt.indent, " \n\r\t") {
106107
t.Errorf("%s: Compact:\n\tgot: %s\n\twant: %s", tt.Where, indentNewlines(got), indentNewlines(tt.indent))
107108
}
108109
})

src/encoding/json/v2_indent.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,8 @@ func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
8888
}
8989

9090
func appendIndent(dst, src []byte, prefix, indent string) ([]byte, error) {
91-
// In v2, trailing whitespace is discarded, while v1 preserved it.
92-
dstLen := len(dst)
93-
if n := len(src) - len(bytes.TrimRight(src, " \n\r\t")); n > 0 {
94-
// Append the trailing whitespace afterwards.
95-
defer func() {
96-
if len(dst) > dstLen {
97-
dst = append(dst, src[len(src)-n:]...)
98-
}
99-
}()
100-
}
10191
// In v2, only spaces and tabs are allowed, while v1 allowed any character.
92+
dstLen := len(dst)
10293
if len(strings.Trim(prefix, " \t"))+len(strings.Trim(indent, " \t")) > 0 {
10394
// Use placeholder spaces of correct length, and replace afterwards.
10495
invalidPrefix, invalidIndent := prefix, indent
@@ -129,5 +120,10 @@ func appendIndent(dst, src []byte, prefix, indent string) ([]byte, error) {
129120
if err != nil {
130121
return dst[:dstLen], transformSyntacticError(err)
131122
}
123+
124+
// In v2, trailing whitespace is discarded, while v1 preserved it.
125+
if n := len(src) - len(bytes.TrimRight(src, " \n\r\t")); n > 0 {
126+
dst = append(dst, src[len(src)-n:]...)
127+
}
132128
return dst, nil
133129
}

src/encoding/json/v2_scanner_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ func TestCompactAndIndent(t *testing.T) {
7474
-5e+2
7575
]`},
7676
{Name(""), "{\"\":\"<>&\u2028\u2029\"}", "{\n\t\"\": \"<>&\u2028\u2029\"\n}"}, // See golang.org/issue/34070
77+
{Name(""), `null`, "null \n\r\t"}, // See golang.org/issue/13520 and golang.org/issue/74806
7778
}
7879
var buf bytes.Buffer
7980
for _, tt := range tests {
@@ -102,7 +103,7 @@ func TestCompactAndIndent(t *testing.T) {
102103
buf.Reset()
103104
if err := Indent(&buf, []byte(tt.compact), "", "\t"); err != nil {
104105
t.Errorf("%s: Indent error: %v", tt.Where, err)
105-
} else if got := buf.String(); got != tt.indent {
106+
} else if got := buf.String(); got != strings.TrimRight(tt.indent, " \n\r\t") {
106107
t.Errorf("%s: Compact:\n\tgot: %s\n\twant: %s", tt.Where, indentNewlines(got), indentNewlines(tt.indent))
107108
}
108109
})

0 commit comments

Comments
 (0)