Reference https://blog.go-zh.org/json-a...EncodingEncode的基本用法是package mainimport ( “encoding/json” “fmt” “os”)type Message struct { Name string Body string Time int64}func main() { message := Message{“Tom”, “Hello”, 1294706395881547000} b, err := json.Marshal(message) if err != nil { fmt.Fprintf(os.Stderr, “Failed to Marshal!”) os.Exit(1) } fmt.Printf("%s", b)}输出为:{“Name”:“Tom”,“Body”:“Hello”,“Time”:1294706395881547000}func Marshal(v interface{}) ([]byte, error)Only data structures that can be represented as valid JSON will be encoded:JSON objects only support string as keys.Channel, complex, and function types cannot be encoded.Cyclic data structures are not supported.Pointers will be encoded as the values they point to(or null if the pointer is nil)json package 只能access the exportede fields. 也就是首字母大写的field. 也就是在data structure中的首字母大写的field才会present in JSON outputDecoding// We must first create a place where the decoded data will be storedvar output Message// Please note that passing the pointer to outputdecodeErr := json.Unmarshal(b, &output)if decodeErr != nil { fmt.Fprintf(os.Stderr, “Failed to Unmarshal json data!err:%s”, err) os.Exit(1)}fmt.Printf("%+v\n", output)Unmarshal是怎么确认json field与data structure的对应关系呢?,其实是通过以下来判断的(优先级从高到低).比如对于JSON Field “Foo"来说,An exported field with a tag of “Foo”.An exported field named “Foo"An exported field named “FOO” or “FoO” or some other case-insensitive match of “Foo"总结下来是: Tag -> Foo -> FOO(case-insensitive match)tag的判定规则如下// Field appears in JSON as key “myName”.Field int json:"myName"// Field appears in JSON as key “myName” and// the field is omitted from the object if its value is empty,// as defined above.Field int json:"myName,omitempty"// Field appears in JSON as key “Field” (the default), but// the field is skipped if empty.// Note the leading comma.Field int json:",omitempty"// Field is ignored by this package.Field int json:"-"// Field appears in JSON as key “-".Field int json:"-,"如果json data 与data structure中只有部分field匹配怎么办?var unmatchedOutput UnmatchMessagemessage1 := // 代表原生字符串面值,没有转义操作,全是字符串的字面值[]byte{{"Name":"Tom","Body":"Hello","Time":1294706395881547000}}decodeErr1 := json.Unmarshal(b, &unmatchedOutput)if decodeErr1 != nil { fmt.Fprintf(os.Stderr, “Failed to unmarshal json data! err:”, err) os.Exit(1)}fmt.Printf(”%+v\n”, unmatchedOutput)输出为{Name:Tom Boy: Tim:0}从上看出,Unmarshal只会decode符合上述3条件的field!This behavior is particularly useful when you wish to pick only a few specific fields out of a large JSON blob.Generic JSON with interface{}Decoding arbitrary data以上2章先跳过去Reference TypesUnmarshal会为Reference Types自动allocated a memory. 注意这里仅仅为在json 中存在的data allocate memory.package mainimport ( “encoding/json” “fmt” “os”)type FamilyMember struct { Name string Age int Parents []string}func main() { family := FamilyMember{“Andy”, 26, []string{“Tom”, “Lucy”}} b, err := json.Marshal(family) if err != nil { fmt.Fprintf(os.Stderr, “Failed to Marshal family!err:%s”, err) os.Exit(1) } fmt.Printf("%s\n”, b) // 注意,此时Parents slice是nil. 在Unmarshal时,会自动为其allcated memory. var output FamilyMember decodeErr := json.Unmarshal(b, &output) if decodeErr != nil { fmt.Fprintf(os.Stderr, “Failed to unmarshal!err:%s”, err.Error()) os.Exit(1) } fmt.Printf(”%+v\n", output)}对于指针也是一样的package mainimport ( “encoding/json” “fmt” “os”)type Bar inttype Foo struct { Bar *Bar}func main() { b := []byte({"Bar":1234}) var data Foo err := json.Unmarshal(b, &data) if err != nil { fmt.Fprintf(os.Stderr, “Failed to unmarshal!err:%s”, err.Error()) os.Exit(1) } fmt.Printf("%+v\n", data) fmt.Printf("%+v\n", *(data.Bar))}输出为:{Bar:0xc42001a120} // 注意此时的地址不为nil了,因为在Unmarshal已经为其allocated了memory1234但是需要注意,Unmarshal只会为json data匹配的field 分配内存,对于没有匹配的,可能还是nil. 所以对于如下的structure,在使用之前还需要认为的判断是否为nil.type IncomingMessage struct { Cmd *Command Msg *Message}Streaming Encoders and Decoderspackage mainimport ( “encoding/json” “log” “os”)func main() { dec := json.NewDecoder(os.Stdin) enc := json.NewEncoder(os.Stdout) for { var v map[string]interface{} if err := dec.Decode(&v); err != nil { log.Println(err) return } for k := range v { if k != “Name” { delete(v, k) } } if err := enc.Encode(&v); err != nil { log.Println(err) } }}