-
Notifications
You must be signed in to change notification settings - Fork 18k
encoding/json: Indent is documented to "have no trailing newline", yet it sometimes does. #13520
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
It's more likely we'll update the docs at this point. But leaving to @rsc to decide. |
I see. For what it's worth, I'll comment that I found it surprising that a func It'd also be consistent with other funcs in Also, this is the additional code I needed to add to my code to produce expected/consistent output: @@ -21,6 +21,14 @@ func run() error {
var out bytes.Buffer
err = json.Indent(&out, in, "", "\t")
if err != nil {
return err
}
+ // TODO: Maybe not here; see https://github.com/golang/go/issues/13520.
+ // Add a newline, if there isn't one already.
+ if l := out.Len(); l != 0 && out.Bytes()[l-1] != '\n' {
+ err = out.WriteByte('\n')
+ if err != nil {
+ return err
+ }
+ }
That wouldn't be needed if I think I like the behavior as documented better, and would hope the implementation is fixed (since that would make |
Well that's sad. It has been that way back at least to Go 1.2 (I don't have earlier Go versions on my Mac). It looks like all trailing spaces are preserved, not just a single newline. Conflicted about changing this. Still thinking. |
You're right. In that case, I'll need to change my code to be quite non-trivial in order to be able to use the result of ...
var out bytes.Buffer
err = json.Indent(&out, in, "", "\t")
if err != nil {
return err
}
// TODO: Maybe not here; see https://github.com/golang/go/issues/13520.
// Trim all whitespace at the end. Then add a single newline.
i := trimRightSpace(out.Bytes())
out.Truncate(i)
err = out.WriteByte('\n')
if err != nil {
return err
}
...
}
// trimRightSpace returns index i, such that s[0:i] is a subslice of s
// by slicing off all trailing white space, as defined by Unicode.
func trimRightSpace(s []byte) int {
i := lastIndexFunc(s, unicode.IsSpace, false)
if i >= 0 && s[i] >= utf8.RuneSelf {
_, wid := utf8.DecodeRune(s[i:])
i += wid
} else {
i++
}
return i
}
// lastIndexFunc is the same as bytes.LastIndexFunc except that if
// truth==false, the sense of the predicate function is inverted.
func lastIndexFunc(s []byte, f func(r rune) bool, truth bool) int {
for i := len(s); i > 0; {
r, size := rune(s[i-1]), 1
if r >= utf8.RuneSelf {
r, size = utf8.DecodeLastRune(s[0:i])
}
i -= size
if f(r) == truth {
return i
}
}
return -1
} Here's an updated playground link: |
Sure, that works. So does:
|
Tested with
go version go1.5.2 darwin/amd64
.I'm reading the documentation for
json.Indent
:https://godoc.org/encoding/json#Indent
Specifically, this part:
But that doesn't always seem to be the case. Depending on whether the input has a trailing newline, so does the output. Here's a quick reproduce program:
https://play.golang.org/p/bSoN4Tl2q_
If I understood the documentation and the output correctly, does this mean there's a bug in
json.Indent
?Edit: Sorry, I accidentally used the word "encode" a few times instead of "indent". That was a typo, now fixed.
The text was updated successfully, but these errors were encountered: