这两天工作中遇到了很多json处理(一看就是写web的...),碰到了很多坑,所以把用法整理了一下放到这里做参考
Encode && Marshal
package main
import (
"bytes"
"encoding/json"
"fmt"
)
type paramsStruct struct {
Id int `json:"id"`
Title string `json:"name"`
Etc etcStruct `json:"etc"`
}
type etcStruct struct {
Content string `json:"content"`
}
func main() {
params := paramsStruct{
Id: 3,
Title: "ha",
Etc: etcStruct{Content: "content"},
}
paramsMap := map[string]interface{}{
"Id": 1,
"title": "ha",
"etc": map[string]interface{}{
"content": "content",
},
}
a, _ := json.Marshal(params)
fmt.Println(string(a))
b, _ := json.Marshal(paramsMap)
fmt.Println(string(b))
var buf bytes.Buffer
json.NewEncoder(&buf).Encode(params)
fmt.Print(buf.String())
var buf2 bytes.Buffer
json.NewEncoder(&buf2).Encode(paramsMap)
fmt.Print(buf2.String())
}
output
{"id":3,"name":"ha","etc":{"content":"content"}}
{"Id":1,"etc":{"content":"content"},"title":"ha"}
{"id":3,"name":"ha","etc":{"content":"content"}}
{"Id":1,"etc":{"content":"content"},"title":"ha"}
Decode && UnMarshal
package main
import (
"encoding/json"
"fmt"
"strings"
)
type paramsStruct struct {
Id int `json:"id"`
Title string `json:"name"`
Etc etcStruct `json:"etc"`
}
type etcStruct struct {
Content string `json:"content"`
}
func main() {
var param paramsStruct
var paramsMap map[string]interface{}
jsonStr := `{"id":3,"name":"ha","etc":{"content":"content"}}`
json.Unmarshal([]byte(jsonStr), ¶m)
json.Unmarshal([]byte(jsonStr), ¶msMap)
fmt.Println(param)
fmt.Println(paramsMap)
json.NewDecoder(strings.NewReader(jsonStr)).Decode(¶m)
json.NewDecoder(strings.NewReader(jsonStr)).Decode(¶msMap)
fmt.Println(param)
fmt.Println(paramsMap)
}
output
{3 ha {content}}
map[etc:map[content:content] id:3 name:ha]
{3 ha {content}}
map[etc:map[content:content] id:3 name:ha]
总结
- 对struct的转换依赖于注解,如果没有依赖于字段名
- Marshal UnMarshal是对[]bype和(struct或者map[string]interface{})做相互转换
- NewEncode参数为io.Writer,bytes.Buffer实现了接口;newDecode参数为io.Reader,可以通过strings.NewReader()方法转换字符串为io.Reader
- Encode时struct 如果没有注解结果为空
其他
- struct 中多一个字段或json 中少一个字段不影响解析.
- 注解中加入omitempty时,encode忽略零值
- json 和struct类型不一致会忽略并报错.解决方法
json:"id,string"- 如下实现
package main
import (
"encoding/json"
"fmt"
"strconv"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func (p *Person) UnmarshalJSON(b []byte) error {
var objMap map[string]*json.RawMessage
err := json.Unmarshal(b, &objMap)
if err != nil {
return err
}
var name string
err = json.Unmarshal(*objMap["name"], &name)
if err != nil {
return err
}
var ageInt int
err = json.Unmarshal(*objMap["age"], &ageInt)
if err != nil {
// age is string
var ageString string
err = json.Unmarshal(*objMap["age"], &ageString)
if err != nil {
return err
}
aI, err := strconv.Atoi(ageString)
if err != nil {
return err
}
p.Age = aI
} else {
p.Age = ageInt
}
p.Name = name
fmt.Printf("%+v", *p)
return nil
}
func main() {
p := `{"name": "John", "age": "10"}`
// p := `{"name": "John", "age": 10}`
newP := Person{}
err := newP.UnmarshalJSON([]byte(p))
if err != nil {
fmt.Printf("Error %+v", err)
}
}