Skip to content
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

encoding/json: Field name tag not respected when encoding if there is a space after ":" #14142

Closed
arcrose opened this issue Jan 28, 2016 · 3 comments

Comments

Projects
None yet
3 participants
@arcrose
Copy link

commented Jan 28, 2016

I've found that, when encoding a struct into JSON, if there is a space after the colon character in the tag for the field in the struct in question, then the field will not be renamed. Below is some very simple code demonstrating what I mean.

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json: "name"`
    Age  int    `json: "age"`
}

func main() {
    p := Person{"Alice", 29}
    bytes, _ := json.Marshal(p)
    fmt.Println(string(bytes))
}

As you can see, in the above code I've made the apparent "mistake" of adding a space in my JSON tags.
If I run this code, the output I get the following output.

{"Name":"Alice","Age":29}

Now if I change the struct definition to the following

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

and then recompile and run the code, I get the expected output

{"name":"Alice","age":29}

What's interesting is that this isn't a problem when decoding JSON. Reintroducing spaces after the colon character, and switching to decoding from bytes, you'll see that the struct is populated properly even though I have switched the order of the fields in the JSON. I take this to mean that the decoder understands the JSON tags even with the space when decoding.

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    Name string `json: "name"`
    Age  int    `json: "age"`
}

func main() {
    data := []byte(`{"age": 29, "name": "Alice"}`)
    p := Person{}
    json.Unmarshal(data, &p)
    fmt.Println(p)
}

The output I get is, as expected,

{Alice 29}

I should note that I've also experimented with using a Decoder and Encoder instead of Unmarshal and Marshal. They suffer from the same problem (and I assume share a similar implementation to their respective counterparts).

I tested this running Go 1.5.3 on the latest OS X. The output of go version is

go version go1.5.3 darwin/amd64

It seems to me that the encoding/json's decoding and encoding functionality should behave the same with regards to how struct tags are treated. I should be able to have spaces after ":" in the tag and still have struct fields encoded such that the right keys are used, especially since decoding isn't affected by this.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jan 28, 2016

It's working on decode because, in the absence of a tag or an exact match, Decode does a case-insensitive match of tag name to field name.

We want field tag parsing to be a simple as possible: no whitespace or any other syntax beyond what is specified. This is working as intended.

@arcrose

This comment has been minimized.

Copy link
Author

commented Jan 29, 2016

@ianlancetaylor Just because it's "intended" to work that way doesn't mean it's good.
This behavior is misleading and confusing. There is no indication, such as a compile-time warning, about the behavior, and it's quite confusing. It necessitates an understanding of a very particular and frankly unusual piece of trivia about the Go compiler, and I think it's not in the language's interest to leave something so vague.
I'm not sure I understand why, in a language whose formatting tools encourage some superfluous whitespace between things like struct field names and their types, a little extra checking can't be done to avoid subtle cases like this.
Can this not be a discussion that isn't just shut down because of what your sacred spec says?

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

commented Jan 29, 2016

Yes, this can be a discussion, but the discussion should not take place on the bug tracker. It's not a bug: the code is working as documented and the documentation seems reasonably clear. For discussions, please see https://golang.org/wiki/Questions . Thanks.

@golang golang locked and limited conversation to collaborators Feb 3, 2017

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.