I want to customize encoding format of a struct but got error: json: error calling MarshalJSON for type main.Info: invalid character 'o' in literal false (expecting 'a') What's 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))
}
JSON objects only support strings as keys; to encode a Go map type it must be of the form map T (where T is any Go type supported by the json package).
The json package provides Decoder and Encoder types to support the common operation of reading and writing streams of JSON data. The NewDecoder and NewEncoder functions wrap the io.Reader and io.Writer interface types.
The Go library is following the spec. The easiest way to do this is with MarshalIndent, which will let you specify how you would like it indented via the indent argument. Thus, json.MarshalIndent (data, "", " ") will pretty-print using four spaces for indentation.
JSON objects only support strings as keys; to encode a Go map type it must be of the form map [string]T (where T is any Go type supported by the json package). Channel, complex, and function types cannot be encoded. Cyclic data structures are not supported; they will cause Marshal to go into an infinite loop.
Your code produces invalid JSON text.
You should write the names of the fields too, and for safety quote both the field names and string
values but don't quote bool
values (else the Go json
package will not unmarshal it into bool
for example). Also enclose your values in brackets {}
like this:
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 }
Output (try the complete application on the Go Playground):
[{"name":"foo","flag":true},{"name":"bar","flag":false}]
But since you're not doing anything special during marshal, just export the fields (by starting them with upper-case letters) and the json
package will marshal/unmarshal it for you automatically:
type Info struct {
Name string
Flag bool
}
Try this version on the Go Playground.
Output (note the upper-cased names "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 like this:
type Info struct {
Name string `json:"name"`
Flag bool `json:"flag"`
}
This will again produce an output with lower-cased names:
[{"name":"foo","flag":true},{"name":"bar","flag":false}]
Read the documentation of the json.Marshal()
function to see what other options and customizations you can do with struct tags.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With