How to set up JSON encoding output in Go?

I want to configure the encoding format of the structure, but I got an error: json: error calling MarshalJSON for type main.Info: invalid character 'o' in literal false (expecting 'a') What is wrong with my code?

package main import ( "bytes" "encoding/json" "fmt" "log" ) type Info struct { name string flag bool } func (i Info) MarshalJSON() ([]byte, error) { var b bytes.Buffer b.Write([]byte(i.name)) if i.flag { b.Write([]byte(`"true"`)) } else { b.Write([]byte(`"false"`)) } return b.Bytes(), nil } func main() { a := []Info{ {"foo", true}, {"bar", false}, } out, err := json.Marshal(a) if err != nil { log.Fatal(err) } fmt.Printf(string(out)) } 
+5
source share
3 answers

Your code displays invalid JSON text.

You should also write the field names, and for security quotes, the field names and string values , but do not contain the bool value (otherwise the Go json package will not untie it in bool , for example). Also enclose your values ​​in brackets {} as follows:

 b.Write([]byte(`{"name":"`)) // started with { b.Write([]byte(i.name)) b.Write([]byte(`","flag":`)) // note the , between values if i.flag { b.Write([]byte(`true`)) // don't quote boolean value } else { b.Write([]byte(`false`)) // don't quote boolean value } b.Write([]byte(`}`)) // must close with } 

Conclusion (try the full app on Go Playground ):

 [{"name":"foo","flag":true},{"name":"bar","flag":false}] 

But since you are not doing anything special during the marshal, just export the fields (by starting them with uppercase letters), and the json package will automatically marshal him / unmarshal:

 type Info struct { Name string Flag bool } 

Try this version on Go Playground .

Exit (pay attention to the names with the upper location "Name" and "Flag" ):

 [{"name":"foo","flag":true},{"name":"bar","flag":false}] 

You can also use tags if you want to use different names in the JSON text as follows:

 type Info struct { Name string `json:"name"` Flag bool `json:"flag"` } 

This again leads to a release with names with a lower oval:

 [{"name":"foo","flag":true},{"name":"bar","flag":false}] 

Read the json.Marshal() function documentation to find out what other parameters and settings you can use with structure tags.

+2
source

Writing custom lines for a buffer type excludes the purpose of json.Marshal() . Maybe something like:

 type Info struct { Name string `json:"name"` // Struct fields should have capital first letter // if you want it to be found by the marshaller. Flag bool `json:"flag"` // json:"flag" assigns the object key in json format } 

And then something like:

 myInfo := Info { Name: "Foo", Flag: true, } slc, _ := json.Marshal(myInfo) fmt.Println(string(slc)) 
0
source

The problem is that you expect a magical event to come within your implementation of MarshalJSON . Unfortunately, you need to look at it as if you were building the entire string from scratch. It means that

 func (i Info) MarshalJSON() ([]byte, error) { var b bytes.Buffer b.Write([]byte(i.name)) if i.flag { b.Write([]byte(`"true"`)) } else { b.Write([]byte(`"false"`)) } return b.Bytes(), nil } 

You need to be more like this;

 func (i Info) MarshalJSON() ([]byte, error) { var b bytes.Buffer b.Write([]byte(`{"name":"`)) b.Write([]byte(i.name)) b.Write([]byte(`","flag":`)) if i.flag { b.Write([]byte(`"true"`)) } else { b.Write([]byte(`"false"`)) } b.Write([]byte(`}`)) } 

In addition, I assume that you legitimately want a string for booleans (otherwise why apply this method at all, right?), If not, then you will want to get rid of if and just use b.Write([]byte(i.flag))

0
source

All Articles