308

I am trying to convert a Go struct to JSON using the json package but all I get is {}. I am certain it is something totally obvious but I don't see it.

package main

import (
    "fmt"
    "encoding/json"
)

type User struct {
    name string
}

func main() {
    user := &User{name:"Frank"}
    b, err := json.Marshal(user)
    if err != nil {
        fmt.Printf("Error: %s", err)
        return;
    }
    fmt.Println(string(b))
}

Then when I try to run it I get this:

$ 6g test.go && 6l -o test test.6 && ./test 
{}
vimdude
  • 4,447
  • 1
  • 25
  • 23
magiconair
  • 6,659
  • 4
  • 29
  • 26

5 Answers5

519

You need to export the User.name field so that the json package can see it. Rename the name field to Name.

package main

import (
    "fmt"
    "encoding/json"
)

type User struct {
    Name string
}

func main() {
    user := &User{Name: "Frank"}
    b, err := json.Marshal(user)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(b))
}

Output:

{"Name":"Frank"}
vimdude
  • 4,447
  • 1
  • 25
  • 23
peterSO
  • 158,998
  • 31
  • 281
  • 276
  • 133
    Note that you can add `\`json:"name"\`` to the end of the struct field definition to preserve the output name. – Dustin Nov 25 '11 at 18:31
  • 17
    I see. I kinda like the language but I think some syntactical elements go to far. If the name of a struct member determines the behavior then this is just wrong. – magiconair Nov 25 '11 at 21:33
  • 2
    Well, having the name determine the behavior can be debated if it is good or bad :) but it sure make it easy to know if a field is exported or not without having to check somewhere else. – Olof Nov 26 '11 at 09:31
  • 8
    @magiconair: _The capitalization of the first rune determines visibility_, is a much more reasonable idea than, _"the name of a struct member determines the behavior"_. The visibility metadata needs to be stored somewhere and needs syntax to express it. Eventually it was determined that co opting the capitalization of the first char works best with fewest trade-offs. Before the Go1 release other schemes were tried and rejected. – deft_code Jun 02 '14 at 06:31
  • 14
    I've come a long way since and like the language including the exporting by capitalization very much now. – magiconair Jun 03 '14 at 08:53
  • 1
    this is... very bad. This means I have to jump through hoops to get move to go when I was previously using a language that allowed for easily using lower case fields. – WreckFish Sep 02 '20 at 19:08
94

Related issue:

I was having trouble converting struct to JSON, sending it as response from Golang, then, later catch the same in JavaScript via Ajax.

Wasted a lot of time, so posting solution here.

In Go:

// web server

type Foo struct {
    Number int    `json:"number"`
    Title  string `json:"title"`
}

foo_marshalled, err := json.Marshal(Foo{Number: 1, Title: "test"})
fmt.Fprint(w, string(foo_marshalled)) // write response to ResponseWriter (w)

In JavaScript:

// web call & receive in "data", thru Ajax/ other

var Foo = JSON.parse(data);
console.log("number: " + Foo.number);
console.log("title: " + Foo.title);
pixel
  • 24,905
  • 36
  • 149
  • 251
Manohar Reddy Poreddy
  • 25,399
  • 9
  • 157
  • 140
  • This writes the json with the initial letter capitalized. How can I write the json string in lower case? EDIT: Make sure to include the quotation marks lol. sigh. – WreckFish Sep 02 '20 at 19:13
14

This is an interesting question, it is very easy using the new go versions. You should do this:

package main

import (
    "fmt"
    "encoding/json"
)

type User struct {
    Name string `json:"name"`
}

func main() {
    user := &User{name:"Frank"}
    b, err := json.Marshal(user)
    if err != nil {
        fmt.Printf("Error: %s", err)
        return;
    }
    fmt.Println(string(b))
}

Change this name to Name.

demented hedgehog
  • 7,007
  • 4
  • 42
  • 49
weiwhy
  • 151
  • 1
  • 2
9

You can define your own custom MarshalJSON and UnmarshalJSON methods and intentionally control what should be included, ex:

package main

import (
    "fmt"
    "encoding/json"
)

type User struct {
    name string
}

func (u *User) MarshalJSON() ([]byte, error) {
    return json.Marshal(&struct {
        Name     string `json:"name"`
    }{
        Name:     "customized" + u.name,
    })
}

func main() {
    user := &User{name: "Frank"}
    b, err := json.Marshal(user)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(b))
}

Hieu Vo
  • 3,105
  • 30
  • 31
7

Struct values encode as JSON objects. Each exported struct field becomes a member of the object unless:

  • the field's tag is "-", or
  • the field is empty and its tag specifies the "omitempty" option.

The empty values are false, 0, any nil pointer or interface value, and any array, slice, map, or string of length zero. The object's default key string is the struct field name but can be specified in the struct field's tag value. The "json" key in the struct field's tag value is the key name, followed by an optional comma and options.

Andrew
  • 7,602
  • 2
  • 34
  • 42
GoLang Master
  • 259
  • 5
  • 5