gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区

站長資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

Go語言中處理json數(shù)據(jù)的方法

Go語言中處理json數(shù)據(jù)的方法

Go json包

Marshal():Go數(shù)據(jù)對象 -> json數(shù)據(jù)

UnMarshal():Json數(shù)據(jù) -> Go數(shù)據(jù)對象

func Marshal(v interface{}) ([]byte, error) func Unmarshal(data []byte, v interface{}) error

構(gòu)建json數(shù)據(jù)

Marshal()和MarshalIndent()函數(shù)可以將數(shù)據(jù)封裝成json數(shù)據(jù)。

1、struct、slice、array、map都可以轉(zhuǎn)換成json

2、struct轉(zhuǎn)換成json的時候,只有字段首字母大寫的才會被轉(zhuǎn)換

3、map轉(zhuǎn)換的時候,key必須為string

4、封裝的時候,如果是指針,會追蹤指針指向的對象進(jìn)行封裝

例如:

有一個struct結(jié)構(gòu):

type Post struct {     Id      int     Content string     Author  string }

這個結(jié)構(gòu)表示博客文章類型,有文章ID,文章內(nèi)容,文章的提交作者。這沒什么可說的,唯一需要指明的是:它是一個struct,struct可以封裝(編碼)成JSON數(shù)據(jù)。

要將這段struct數(shù)據(jù)轉(zhuǎn)換成json,只需使用Marshal()即可。如下:

post := &Post{1, "Hello World", "userA"} b, err := json.Marshal(post) if err != nil {     fmt.Println(nil) }

Marshal()返回的是一個[]byte類型,現(xiàn)在變量b就已經(jīng)存儲了一段[]byte類型的json數(shù)據(jù),可以輸出它:

fmt.Println(string(b))

結(jié)果:

{"Id":1,"Content":"Hello World","Author":"userA"}

可以在封裝成json的時候進(jìn)行"美化",使用MarshalIndent()即可自動添加前綴(前綴字符串一般設(shè)置為空)和縮進(jìn):

c,err := json.MarshalIndent(post,"","t") if err != nil {     fmt.Println(nil) } fmt.Println(string(c))

結(jié)果:

{     "Id": 1,     "Content": "Hello World",     "Author": "userA" }

除了struct,array、slice、map結(jié)構(gòu)都能解析成json,但是map解析成json的時候,key必須只能是string,這是json語法要求的。

例如:

// slice -> json s := []string{"a", "b", "c"} d, _ := json.MarshalIndent(s, "", "t") fmt.Println(string(d))  // map -> json m := map[string]string{     "a":"aa",     "b":"bb",     "c":"cc", } e,_ := json.MarshalIndent(m,"","t") fmt.Println(string(e))

返回結(jié)果:

[     "a",     "b",     "c" ] {     "a": "aa",     "b": "bb",     "c": "cc" }

使用struct tag輔助構(gòu)建json

struct能被轉(zhuǎn)換的字段都是首字母大寫的字段,但如果想要在json中使用小寫字母開頭的key,可以使用struct的tag來輔助反射。

例如,Post結(jié)構(gòu)增加一個首字母小寫的字段createAt。

type Post struct {     Id      int      `json:"ID"`     Content string   `json:"content"`     Author  string   `json:"author"`     Label   []string `json:"label"` }   postp := &Post{     2,     "Hello World",     "userB",     []string{"linux", "shell"},     }  p, _ := json.MarshalIndent(postp, "", "t") fmt.Println(string(p))

結(jié)果:

{     "ID": 2,     "content": "Hello World",     "author": "userB",     "label": [         "linux",         "shell"     ] }

使用struct tag的時候,幾個注意點:

1、tag中標(biāo)識的名稱將稱為json數(shù)據(jù)中key的值

2、tag可以設(shè)置為`json:"-"`來表示本字段不轉(zhuǎn)換為json數(shù)據(jù),即使這個字段名首字母大寫

如果想要json key的名稱為字符"-",則可以特殊處理`json:"-,"`,也就是加上一個逗號

3、如果tag中帶有,omitempty選項,那么如果這個字段的值為0值,即false、0、""、nil等,這個字段將不會轉(zhuǎn)換到j(luò)son中

4、如果字段的類型為bool、string、int類、float類,而tag中又帶有,string選項,那么這個字段的值將轉(zhuǎn)換成json字符串

例如:

type Post struct {     Id      int      `json:"ID,string"`     Content string   `json:"content"`     Author  string   `json:"author"`     Label   []string `json:"label,omitempty"` }

解析json數(shù)據(jù)到struct(結(jié)構(gòu)已知)

json數(shù)據(jù)可以解析到struct或空接口interface{}中(也可以是slice、map等)。理解了上面構(gòu)建json時的tag規(guī)則,理解解析json就很簡單了。

例如,下面是一段json數(shù)據(jù):

{     "id": 1,     "content": "hello world",     "author": {         "id": 2,         "name": "userA"     },     "published": true,     "label": [],     "nextPost": null,     "comments": [{             "id": 3,             "content": "good post1",             "author": "userB"         },         {             "id": 4,             "content": "good post2",             "author": "userC"         }     ] }

分析下這段json數(shù)據(jù):

1、頂層的大括號表示是一個匿名對象,映射到Go中是一個struct,假設(shè)這個struct名稱為Post

2、頂層大括號里的都是Post結(jié)構(gòu)中的字段,這些字段因為都是json數(shù)據(jù),所以必須都首字母大寫,同時設(shè)置tag,tag中的名稱小寫

3、其中author是一個子對象,映射到Go中是另一個struct,在Post中這個字段的名稱為Author,假設(shè)名稱和struct名稱相同,也為Author

4、label是一個數(shù)組,映射到Go中可以是slice,也可以是array,且因為json array為空,所以Go中的slice/array類型不定,比如可以是int,可以是string,也可以是interface{},對于這里的示例來說,我們知道標(biāo)簽肯定是string

5、nextPost是一個子對象,映射到Go中是一個struct,但因為json中這個對象為null,表示這個對象不存在,所以無法判斷映射到Go中struct的類型。但對此處的示例來說,是沒有下一篇文章,所以它的類型應(yīng)該也是Post類型

6、comment是子對象,且是數(shù)組包圍的,映射到Go中,是一個slice/array,slice/array的類型是一個struct

分析之后,對應(yīng)地去構(gòu)建struct和struct的tag就很容易了。如下,是根據(jù)上面分析構(gòu)建出來的數(shù)據(jù)結(jié)構(gòu):

type Post struct {     ID        int64         `json:"id"`            Content   string        `json:"content"`       Author    Author        `json:"author"`        Published bool          `json:"published"`     Label     []string      `json:"label"`         NextPost  *Post         `json:"nextPost"`      Comments  []*Comment    `json:"comments"`  }  type Author struct {     ID   int64  `json:"id"`       Name string `json:"name"` }  type Comment struct {     ID      int64  `json:"id"`          Content string `json:"content"`     Author  string `json:"author"`  }

注意,前面在介紹構(gòu)建json數(shù)據(jù)的時候說明過,指針會進(jìn)行追蹤,所以這里反推出來的struct中使用指針類型是沒問題的。

于是,解析上面的json數(shù)據(jù)到Post類型的對象中,假設(shè)這個json數(shù)據(jù)存放在a.json文件中。代碼如下:

func main() {     // 打開json文件     fh, err := os.Open("a.json")     if err != nil {         fmt.Println(err)         return     }     defer fh.Close()     // 讀取json文件,保存到j(luò)sonData中     jsonData, err := ioutil.ReadAll(fh)     if err != nil {         fmt.Println(err)         return     }          var post Post     // 解析json數(shù)據(jù)到post中     err = json.Unmarshal(jsonData, &post)     if err != nil {         fmt.Println(err)         return     }     fmt.Println(post) }

輸出結(jié)果:

{1 hello world {2 userA} true [] <nil> [0xc042072300 0xc0420723c0]}

也許你已經(jīng)感受到了,從json數(shù)據(jù)反推算struct到底有多復(fù)雜,雖然邏輯不難,但如果數(shù)據(jù)復(fù)雜一點,這是件非常惡心的事情。所以,使用別人寫好的工具來自動轉(zhuǎn)換吧。本文后面有推薦json到數(shù)據(jù)結(jié)構(gòu)的自動轉(zhuǎn)換工具。

解析json到interface(結(jié)構(gòu)未知)

上面是已知json數(shù)據(jù)結(jié)構(gòu)的解析方式,如果json結(jié)構(gòu)是未知的或者結(jié)構(gòu)可能會發(fā)生改變的情況,則解析到struct是不合理的。這時可以解析到空接口interface{}或map[string]interface{}類型上,這兩種類型的結(jié)果是完全一致的。

解析到interface{}上時,Go類型和JSON類型的對應(yīng)關(guān)系如下

  JSON類型             Go類型                 --------------------------------------------- JSON objects    <-->  map[string]interface{}  JSON arrays     <-->  []interface{}           JSON booleans   <-->  bool                    JSON numbers    <-->  float64                 JSON strings    <-->  string                  JSON null       <-->  nil

例如:

func main() {     // 讀取json文件     fh, err := os.Open("a.json")     if err != nil {         fmt.Println(err)         return     }     defer fh.Close()     jsonData, err := ioutil.ReadAll(fh)     if err != nil {         fmt.Println(err)         return     }          // 定義空接口接收解析后的json數(shù)據(jù)     var unknown interface{}     // 或:map[string]interface{} 結(jié)果是完全一樣的     err = json.Unmarshal(jsonData, &unknown)     if err != nil {         fmt.Println(err)         return     }     fmt.Println(unknown) }

輸出結(jié)果:

map[nextPost:<nil> comments:[map[id:3 content:good post1 author:userB] map[id:4 content:good post2 author:userC]] id:1 content:hello world author:map[id:2 name:userA] published:true label:[]]

上面將輸出map結(jié)構(gòu)。這是顯然的,因為類型對應(yīng)關(guān)系中已經(jīng)說明了,json object解析到Go interface的時候,對應(yīng)的是map結(jié)構(gòu)。如果將上面輸出的結(jié)構(gòu)進(jìn)行一下格式化,得到的將是類似下面的結(jié)構(gòu):

map[     nextPost:<nil>     comments:[         map[             id:3             content:good post1             author:userB         ]         map[             id:4             content:good post2             author:userC         ]     ]     id:1     content:hello world     author:map[         id:2         name:userA     ]     published:true     label:[] ]

現(xiàn)在,可以從這個map中去判斷類型、取得對應(yīng)的值。但是如何判斷類型?可以使用類型斷言:

func main() {     // 讀取json數(shù)據(jù)     fh, err := os.Open("a.json")     if err != nil {         fmt.Println(err)         return     }     defer fh.Close()     jsonData, err := ioutil.ReadAll(fh)     if err != nil {         fmt.Println(err)         return     }          // 解析json數(shù)據(jù)到interface{}     var unknown interface{}     err = json.Unmarshal(jsonData, &unknown)     if err != nil {         fmt.Println(err)         return     }      // 進(jìn)行斷言,并switch匹配     m := unknown.(map[string]interface{})     for k, v := range m {         switch vv := v.(type) {         case string:             fmt.Println(k, "type: stringnvalue: ", vv)             fmt.Println("------------------")         case float64:             fmt.Println(k, "type: float64nvalue: ", vv)             fmt.Println("------------------")         case bool:             fmt.Println(k, "type: boolnvalue: ", vv)             fmt.Println("------------------")         case map[string]interface{}:             fmt.Println(k, "type: map[string]interface{}nvalue: ", vv)             for i, j := range vv {                 fmt.Println(i,": ",j)             }             fmt.Println("------------------")         case []interface{}:             fmt.Println(k, "type: []interface{}nvalue: ", vv)             for key, value := range vv {                 fmt.Println(key, ": ", value)             }             fmt.Println("------------------")         default:             fmt.Println(k, "type: nilnvalue: ", vv)             fmt.Println("------------------")         }     } }

結(jié)果如下:

comments type: []interface{} value:  [map[id:3 content:good post1 author:userB] map[author:userC id:4 content:good post2]] 0 :  map[id:3 content:good post1 author:userB] 1 :  map[id:4 content:good post2 author:userC] ------------------ id type: float64 value:  1 ------------------ content type: string value:  hello world ------------------ author type: map[string]interface{} value:  map[id:2 name:userA] name :  userA id :  2 ------------------ published type: bool value:  true ------------------ label type: []interface{} value:  [] ------------------ nextPost type: nil value:  <nil> ------------------

可見,從interface中解析非常復(fù)雜,而且可能因為嵌套結(jié)構(gòu)而導(dǎo)致無法正確迭代遍歷。這時候,可以使用第三方包simplejson,見后文。

解析、創(chuàng)建json流

除了可以直接解析、創(chuàng)建json數(shù)據(jù),還可以處理流式數(shù)據(jù)。

1、type Decoder解碼json到Go數(shù)據(jù)結(jié)構(gòu)

2、ype Encoder編碼Go數(shù)據(jù)結(jié)構(gòu)到j(luò)son

例如:

const jsonStream = `     {"Name": "Ed", "Text": "Knock knock."}     {"Name": "Sam", "Text": "Who's there?"}     {"Name": "Ed", "Text": "Go fmt."}     {"Name": "Sam", "Text": "Go fmt who?"}     {"Name": "Ed", "Text": "Go fmt yourself!"} ` type Message struct {     Name, Text string } dec := json.NewDecoder(strings.NewReader(jsonStream)) for {     var m Message     if err := dec.Decode(&m); err == io.EOF {         break     } else if err != nil {         log.Fatal(err)     }     fmt.Printf("%s: %sn", m.Name, m.Text) }

輸出:

Ed: Knock knock. Sam: Who's there? Ed: Go fmt. Sam: Go fmt who? Ed: Go fmt yourself!

再例如,從標(biāo)準(zhǔn)輸入讀json數(shù)據(jù),解碼后刪除名為Name的元素,最后重新編碼后輸出到標(biāo)準(zhǔn)輸出。

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)         }     } }

贊(0)
分享到: 更多 (0)
?
網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区
婷婷五月综合缴情在线视频| 成人av一级片| 日本中文字幕二区| 青青草原成人网| 欧美日韩在线一| 夜夜添无码一区二区三区| 99亚洲精品视频| 国产对白在线播放| 亚洲国产精品影视| 男人的天堂成人| 欧美 国产 精品| 久久久久久av无码免费网站下载| 永久av免费在线观看| 日本美女久久久| 免费在线观看污污视频| 亚洲国产欧美91| 天天综合五月天| 2018中文字幕第一页| 久久99中文字幕| 欧美老熟妇喷水| 日本精品一区二区三区四区| 欧美aⅴ在线观看| 在线免费观看视频黄| 欧美成人乱码一二三四区免费| 最新天堂在线视频| 日本特级黄色大片| 免费在线看黄色片| 国产午夜大地久久| 91av俱乐部| 91免费视频污| 国产性生活免费视频| 欧美男女爱爱视频| 香蕉视频网站入口| 国产九九九视频| 欧美,日韩,国产在线| 无人在线观看的免费高清视频| 一道本在线免费视频| 400部精品国偷自产在线观看| 久久这里只有精品23| av天堂永久资源网| 日日干日日操日日射| 国产尤物av一区二区三区| 日韩av黄色网址| 国产精品999.| 欧美深夜福利视频| 99精品999| 国产av天堂无码一区二区三区| 成人3d动漫一区二区三区| 日韩视频在线观看一区二区三区| 久久av综合网| 天天色综合天天色| 久久成人福利视频| 天堂在线中文在线| 蜜臀av无码一区二区三区| mm131国产精品| 无码专区aaaaaa免费视频| 高清av免费看| 亚洲熟妇无码一区二区三区| 国产乱女淫av麻豆国产| 自拍日韩亚洲一区在线| 亚洲美女自拍偷拍| 中文字幕一区二区三区四区在线视频| 国产人妻人伦精品| 天堂社区在线视频| 你真棒插曲来救救我在线观看| av噜噜在线观看| 精品视频无码一区二区三区| 99国产精品白浆在线观看免费| 无尽裸体动漫2d在线观看| 18岁网站在线观看| 久久亚洲a v| 国产精品美女在线播放| 亚洲三级视频网站| 国产精品动漫网站| 精品这里只有精品| cao在线观看| 国产一级大片免费看| 国产精品久久久久久久99| 国产wwwxx| 日韩精品无码一区二区三区免费| 日韩av新片网| 久久av综合网| www成人免费| 免费的一级黄色片| 青青草视频国产| 国产一级大片免费看| 偷拍盗摄高潮叫床对白清晰| 高潮一区二区三区| 色播五月综合网| 中文字幕 91| 日韩精品视频一二三| 黄色片视频在线| 久久国产这里只有精品| 在线观看亚洲色图| 三级视频中文字幕| 日本xxxx黄色| 亚洲精品视频三区| 一级黄色片在线免费观看| 污污网站免费观看| 日本网站在线看| 黑人巨大国产9丨视频| 无颜之月在线看| 996这里只有精品| 免费拍拍拍网站| 国产妇女馒头高清泬20p多| 日韩亚洲欧美视频| 国产免费一区二区三区视频| www.爱色av.com| 国产成人手机视频| 久国产精品视频| 在线观看成人免费| 久草免费福利在线| 欧美 国产 小说 另类| 久久久精品三级| 国产资源中文字幕| 青青青青在线视频| 久久精品网站视频| 天天影视色综合| 亚洲色图都市激情| 成年人视频网站免费观看| 亚洲一级免费观看| 好色先生视频污| 欧美日韩亚洲一| 污污网站免费观看| 隔壁人妻偷人bd中字| 国产精品天天av精麻传媒| 国产高清av片| 欧美网站免费观看| 国产精品探花在线播放| 国产精品又粗又长| 伊人色在线观看| 老太脱裤子让老头玩xxxxx| 中文字幕第80页| 国产制服91一区二区三区制服| 免费无码av片在线观看| 亚洲欧美日韩网站| 漂亮人妻被中出中文字幕| 亚洲日本黄色片| 欧美日韩亚洲一| 黄色小视频大全| 久久99爱视频| 久久久999视频| 日韩精品一区二区三区电影| 免费看黄色一级大片| 韩国无码av片在线观看网站| 九九热免费精品视频| 日本午夜激情视频| 日本一级淫片演员| 亚洲免费看av| 免费看一级大黄情大片| 成年人黄色在线观看| 日本免费一级视频| 精品国产一区二区三区无码| 久久人人爽av| 精品99在线视频| 国产精品久久久久久久乖乖| av中文字幕网址| 高清一区二区视频| 国产第一页视频| www精品久久| 成人短视频在线观看免费| 亚洲第一成肉网| 黄色手机在线视频| 999香蕉视频| 久草青青在线观看| 精品视频在线观看一区| 性欧美18一19内谢| 亚洲最大天堂网| 亚洲精品午夜在线观看| 国产v亚洲v天堂无码久久久| 国产精品12345| 日韩精品免费一区| 欧美aaa在线观看| 激情久久综合网| 热久久久久久久久| 五月天婷婷影视| 九九九九九伊人| 99九九精品视频| 一区二区三区国产好的精华液| 人妻丰满熟妇av无码区app| 亚洲人成色77777| 国产偷人视频免费| 88av.com| 色婷婷成人在线| 中文字幕一区久久| 中文字幕第22页| 精品一区二区成人免费视频| 今天免费高清在线观看国语| 国产小视频免费| 成人午夜精品久久久久久久蜜臀| 亚洲色欲久久久综合网东京热| 亚洲人成无码网站久久99热国产| 久久国产精品视频在线观看| 5月婷婷6月丁香| 欧美黑人又粗又大又爽免费| 国产又粗又长又大的视频| 亚洲人视频在线| 男女激烈动态图| 男女啪啪免费视频网站| 毛片av免费在线观看|