json.Marshal(struct) returns “{}”

2019-01-01 02:29发布

问题:

type TestObject struct {
    kind string `json:\"kind\"`
    id   string `json:\"id, omitempty\"`
    name  string `json:\"name\"`
    email string `json:\"email\"`
}

func TestCreateSingleItemResponse(t *testing.T) {
    testObject := new(TestObject)
    testObject.kind = \"TestObject\"
    testObject.id = \"f73h5jf8\"
    testObject.name = \"Yuri Gagarin\"
    testObject.email = \"Yuri.Gagarin@Vostok.com\"

    fmt.Println(testObject)

    b, err := json.Marshal(testObject)

    if err != nil {
        fmt.Println(err)
    }

    fmt.Println(string(b[:]))
}

Here is the output:

[ `go test -test.run=\"^TestCreateSingleItemResponse$\"` | done: 2.195666095s ]
    {TestObject f73h5jf8 Yuri Gagarin Yuri.Gagarin@Vostok.com}
    {}
    PASS

Why is the JSON essentially empty?

回答1:

You need to export the fields in TestObject by capitalizing the first letter in the field name. Change kind to Kind and so on.

type TestObject struct {
 Kind string `json:\"kind\"`
 Id   string `json:\"id,omitempty\"`
 Name  string `json:\"name\"`
 Email string `json:\"email\"`
}

The encoding/json package and similar packages ignore unexported fields.

The `json:\"...\"` strings that follow the field declarations are struct tags. The tags in this struct set the names of the struct\'s fields when marshaling to and from JSON.

playground



回答2:

  • When the first letter is capitalised, the identifier is public to any piece of code that you want to use.
  • When the first letter is lowercase, the identifier is private and could only be accessed within the package it was declared.

Examples

 var aName // private

 var BigBro // public (exported)

 var 123abc // illegal

 func (p *Person) SetEmail(email string) {  // public because SetEmail() function starts with upper case
    p.email = email
 }

 func (p Person) email() string { // private because email() function starts with lower case
    return p.email
 }