使用Golang解析Yaml、Json、Xml文件

本文转载自微信公众号「运维开发故事」,使用作者wanger 。解析件转载本文请联系运维开发故事公众号。使用

大家好,解析件我是使用wanger。

解析和生成yaml文件

YAML(YAML 不是解析件标记语言)是一种人类可读的数据序列化语言。它通常用于配置文件,使用但也用于数据存储或传输。解析件YAML 本身支持三种基本数据类型:标量(例如字符串、使用整数和浮点数)、解析件列表和映射(字典/哈希)。使用我们使用 yaml.v3 包来解析yaml文件

go get gopkg.in/yaml.v3 

解析yaml

func Unmarshal(in []byte,解析件 out interface{ }) (err error) 

我们使用 Unmarshal来解析yaml yaml文件内容如下:

- name: wanger   age: 24   address: beijing   hobby:     - literature     - social - name: 冬哥   age: 30   address: chengdu   hobby:     - basketball     - guitar - name: 华子   age: 27   address: shenzhen   hobby:     - 王者荣耀 - name: 乔克   age: 29   address: chongqing   hobby:     - 阅读     - 王者荣耀 - name: 夏老师   age: 27   address: chengdu   hobby:     - 吃吃喝喝 - name: 姜总   age: 25   address: shanghai   hobby:     - talkshow - name: 郑哥   age: 30   address: beijing   hobby:     - 阅读     - 复读机 

读取test.yaml

package main import (  "fmt"  "gopkg.in/yaml.v2"  "io/ioutil"  "gopkg.in/yaml.v3"  "log" ) type Users struct {   Name   string      `yaml:"name"`  Age    int8        `yaml:"age"`  Address  string `yaml:"address"`  Hobby []string `yaml:"hobby"` } func main() {   file, err := ioutil.ReadFile("test.yaml")  if err != nil {    log.Fatal(err)  }  var data [7]Users  err2 := yaml.Unmarshal(file, &data)  if err2 != nil {    log.Fatal(err2)  }  for _, v := range data {    fmt.Println(v)  } } 

输出内容如下

{ wanger 24 beijing [literature social]} { 冬哥 30 chengdu [basketball guitar]} { 华子 27 shenzhen [王者荣耀]} { 乔克 29 chongqing [阅读 王者荣耀]} { 夏老师 27 chengdu [吃吃喝喝]} { 姜总 25 shanghai [钓鱼  音乐 美食  酒talkshow]} { 郑哥 30 beijing [阅读 复读机]} 

生成yaml

func Marshal(in interface{ }) (out []byte, err error) 

我们使用 Marshal来生成yaml,生成一个关于我们团队信息的使用yaml文件吧 可以通过定义结构体yaml标签来自定义输出的yaml文件的高防服务器键名

package main import (  "fmt"  "gopkg.in/yaml.v3" ) type Users struct {   Name   string      `yaml:"name"`  Age    int8        `yaml:"age"`  Address  string `yaml:"address"`  Hobby []string `yaml:"hobby"` } func main() {   wanger := Users{    Name: "wanger",   Age:  24,   Address: "beijing",   Hobby: []string{ "literature", "social"},  }  dongdong := Users{    Name: "冬哥",   Age:  30,   Address: "chengdu",   Hobby: []string{ "basketball", "guitar"},  }  xialaoshi := Users{    Name: "夏老师",   Age:  29,   Address: "chengdu",   Hobby: []string{ "吃吃喝喝"},  }  huazai := Users{    Name: "华子",   Age:  28,   Address: "shenzhen",   Hobby: []string{ "王者荣耀"},  }  qiaoke := Users{    Name: "乔克",   Age:  30,   Address: "chongqing",   Hobby: []string{ "阅读", "王者荣耀"},  }  jiangzong := Users{    Name: "姜总",   Age:  25,   Address: "shanghai",   Hobby: []string{ "钓鱼","音乐","美食","酒"},  }  zhengge := Users{    Name: "郑哥",   Age:  30,   Address: "beijing",   Hobby: []string{ "阅读", "复读机"},  }     userlist:=[7]Users{ wanger,dongdong,huazai,qiaoke,xialaoshi,jiangzong,zhengge}  yamlData, err := yaml.Marshal(&userlist)  if err != nil {    fmt.Printf("Error while Marshaling. %v", err)  }  fmt.Println(string(yamlData))     fileName := "test.yaml"     err = ioutil.WriteFile(fileName, yamlData, 0644)     if err != nil {          panic("Unable to write data into the file")     } }     

生成的yaml信息如下

- name: wanger   age: 24   address: beijing   hobby:     - literature     - social - name: 冬哥   age: 30   address: chengdu   hobby:     - basketball     - guitar - name: 华子   age: 27   address: shenzhen   hobby:     - 王者荣耀 - name: 乔克   age: 29   address: chongqing   hobby:     - 阅读     - 王者荣耀 - name: 夏老师   age: 27   address: chengdu   hobby:     - 吃吃喝喝 - name: 姜总   age: 25   address: shanghai   hobby:     - 钓鱼       - 音乐     - 美食      - 酒 - name: 郑哥   age: 30   address: beijing   hobby:     - 阅读     - 复读机 

解析和生成json文件

我们使用encoding/json标准库包来实现json文件的解析与生成

读取和解析json文件

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

我这里定义了一个user.json文件

{    "users": [     {        "name": "wanger",       "address": "beijing",       "age": 24,       "social": {          "mobile": "111111111",         "email": "wanger@163.com"       }     },     {        "name": "dongdong",       "address": "chengdu",       "age": 30,       "social": {          "mobile": "2222222222222222",         "emial": "dongdong@163.com"       }     },     {        "name": "夏老师",       "address": "chengdu",       "age": 29,       "social": {          "mobile": "2232222222222222",         "emial": "xialaoshi@163.com"       }     },     {        "name": "郑哥",       "address": "beijing",       "age": 30,       "social": {          "mobile": "12222211111",         "email": "zhengge@163.com"       }     },     {        "name": "姜总",       "address": "shanghai",       "age": 25,       "social": {          "mobile": "111122211",         "email": "jaingzong@163.com"       }     },     {        "name": "乔克",       "address": "chongqing",       "age": 30,       "social": {          "mobile": "11333331111111",         "email": "qiaoke@163.com"       }     },     {        "name": "华仔",       "address": "shenzhen",       "age": 28,       "social": {          "mobile": "113311111",         "email": "huazai@163.com"       }     }   ] } 

读取user.json文件

package main import (  "encoding/json"  "fmt"  "io/ioutil"  "os"  "strconv" ) func main() {   jsonFile,err:=os.Open("user.json")  if err != nil {    fmt.Println(err)  }  fmt.Println("Successfully Opened users.json")  defer jsonFile.Close()  byteValue,_:=ioutil.ReadAll(jsonFile)  var users Users  json.Unmarshal(byteValue,&users)  for i :=0;i<len(users.Users);i++ {    fmt.Println("User Type: "+ users.Users[i].Address)   fmt.Println("User Age: "+strconv.Itoa(users.Users[i].Age))   fmt.Println("User Name: "+users.Users[i].Name)   fmt.Println("User Email: "+users.Users[i].Social.Email)  }  var result Users  json.Unmarshal(byteValue,&result) } type Users struct {   Users []User `json:"users"` } type User struct {   Name string `json:"name"`  Address string `json:"address"`  Age int `json:"Age"`  Social Social `json:"social"` } type Social struct {   Mobile string `json:"mobile"`  Email string `json:"email"` } 

输出结果如下

Successfully Opened users.json User Type: beijing User Age: 24 User Name: wanger User Email: wanger@163.com User Type: chengdu User Age: 30 User Name: dongdong User Email:  User Type: chengdu User Age: 28 User Name: 夏老师 User Email:  User Type: beijing User Age: 30 User Name: 郑哥 User Email: zhengge@163.com User Type: shanghai User Age: 25 User Name: 姜总 User Email: jaingzong@163.com User Type: chongqing User Age: 29 User Name: 乔克 User Email: qiaoke@163.com User Type: shenzhen User Age: 28 User Name: 华仔 User Email: huazai@163.com 

当然有时候我们可能不知道要读取的json数据结构,这就没办法预定义结构体,解析件那么我们可以使用**map[string]interface{ }**类型来解析json。使用

var result map[string]interface{ } err = json.Unmarshal(byteValue, &result) fmt.Printf("%+v\n", result) 

输出信息如下:

map[users:[map[address:beijing age:24 name:wanger social:map[email:wanger@163.com mobile:111111]] map[address:chengdu age:30 name:dongdong social:map[emial:dongdong@163.com mobil222222222222222]] map[address:chengdu age:28 name:夏老师 social:map[emial:xialaoshi@163.cmobile:2232222222222222]] map[address:beijing age:30 name:郑哥 social:map[email:zhengge@1com mobile:12222211111]] map[address:shanghai age:25 name:姜总 social:map[email:jaingzong3.com mobile:111122211]] map[address:chongqing age:29 name:乔克 social:map[email:qiaoke@1com mobile:11333331111111]] map[address:shenzhen age:28 name:华仔 social:map[email:huazai3.com mobile:113311111]]]] 

生成json文件

func Marshal(v interface{ }) ([]byte, error) package main import (  "encoding/json"  "fmt"  "io/ioutil" ) func main() {   wanger:=User{ Address:"beijing",Name:"wanger",Age:24,Social:Social{ Email:"wanger@163.com",Mobile:"111111111111"}}  huazi:=User{ Address:"shenzhen",Name:"huazai",Age:28,Social:Social{ Email:"huazai@163.com",Mobile:"111122211111"}}  qiaoke:=User{ Address:"chongqing",Name:"qiaoke",Age:30,Social:Social{ Email:"qiaoke@163.com",Mobile:"13332211111"}}  xialaoshi:=User{ Address:"chengdu",Name:"夏老师",Age:29,Social:Social{ Email:"xialaoshi@163.com",Mobile:"11144445411111"}}  jiangzong:=User{ Address:"shanghai",Name:"姜总",Age:25,Social:Social{ Email:"jiangzong@163.com",Mobile:"111222445211111"}}  dongdong:=User{ Address:"chengdu",Name:"冬哥",Age:30,Social:Social{ Email:"dongdong@163.com",Mobile:"1155555211111"}}  zhengge:=User{ Address:"beijing",Name:"郑哥",Age:24,Social:Social{ Email:"zhengge@163.com",Mobile:"1112224566211111"}}  result:=Users{ Users: []User{ wanger,huazi,jiangzong,xialaoshi,qiaoke,dongdong,zhengge}}  bytearray,err:=json.Marshal(result)  if err!=nil {    fmt.Println(err)  }  fmt.Println(string(bytearray))  fileName := "user.json"  err = ioutil.WriteFile(fileName, bytearray, 0644)  if err != nil {    panic("Unable to write data into the file")  } } type Users struct {   Users []User `json:"users"` } type User struct {   Name string `json:"name"`  Address string `json:"address"`  Age int `json:"Age"`  Social Social `json:"social"` } type Social struct {   Mobile string `json:"mobile"`  Email string `json:"email"` } 

输出内容如下

{ "users":[{ "name":"wanger","address":"beijing","Age":24,"social":{ "mobile":"111111111111","email":"wanger@163.com"}},{ "name":"huazai","address":"shenzhen","Age":28,"social":{ "mobile":"111122211111","email":"huazai@163.com"}},{ "name":"姜总","address":"shanghai","Age":25,"social":{ "mobile":"111222445211111","email":"jiangzong@163.com"}},{ "name":"夏老师","address":"chengdu","Age":29,"social":{ "mobile":"11144445411111","email":"xialaoshi@163.com"}},{ "name":"qiaoke","address":"chongqing","Age":30,"social":{ "mobile":"13332211111","email":"qiaoke@163.com"}},{ "name":"冬哥","address":"chengdu","Age":30,"social":{ "mobile":"1155555211111","email":"dongdong@163.com"}},{ "name":"郑哥","address":"beijing","Age":24,"social":{ "mobile":"1112224566211111","email":"zhengge@163.com"}}]} 

可以看出上面输出的json并不是很美观,可以使用更易读的函数**json.MarshalIndent()**函数,MarshalIndent()可以定义输出的前缀和缩进

bytearray,err:=json.MarshalIndent(result,""," ") if err!=nil {   fmt.Println(err) } fmt.Println(string(bytearray)) 

输出内容如下,比之前看起来好多了

{   "users": [   {     "name": "wanger",    "address": "beijing",    "Age": 24,    "social": {      "mobile": "111111111111",     "email": "wanger@163.com"    }   },   {     "name": "huazai",    "address": "shenzhen",    "Age": 28,    "social": {      "mobile": "111122211111",     "email": "huazai@163.com"    }   },   {     "name": "姜总",    "address": "shanghai",    "Age": 25,    "social": {      "mobile": "111222445211111",     "email": "jiangzong@163.com"    }   },   {     "name": "夏老师",    "address": "chengdu",    "Age": 29,    "social": {      "mobile": "11144445411111",     "email": "xialaoshi@163.com"    }   },   {     "name": "qiaoke",    "address": "chongqing",    "Age": 30,    "social": {      "mobile": "13332211111",     "email": "qiaoke@163.com"    }   },   {     "name": "冬哥",    "address": "chengdu",    "Age": 30,    "social": {      "mobile": "1155555211111",     "email": "dongdong@163.com"    }   },   {     "name": "郑哥",    "address": "beijing",    "Age": 24,    "social": {      "mobile": "1112224566211111",     "email": "zhengge@163.com"    }   }  ] } 

解析和生成xml文件

解析xml文件

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

定义一个user.xml文件

<?xml version="1.0" encoding="UTF-8"?> <users>     <user address="beijing">         <name>wanger</name>         <age>24</age>         <social>             <email>wanger@163.com</email>             <mobile>1233455464</mobile>         </social>     </user>     <user address="chengdu">         <name>冬哥</name>         <age>30</age>         <social>             <email>dongge@163.com</email>             <mobile>12245555464</mobile>         </social>     </user>     <user address="chengdu">         <name>夏老师</name>         <age>29</age>         <social>             <email>xialaoshi@163.com</email>             <mobile>12335677464</mobile>         </social>     </user>     <user address="beijing">         <name>郑哥</name>         <age>30</age>         <social>             <email>zhengge@163.com</email>             <mobile>12334355464</mobile>         </social>     </user>     <user address="shanghai">         <name>姜总</name>         <age>25</age>         <social>             <email>jiangzong@163.com</email>             <mobile>123565455464</mobile>         </social>     </user>     <user address="chongqing">         <name>乔克</name>         <age>29</age>         <social>             <email>qiaoke@163.com</email>             <mobile>124676755464</mobile>         </social>     </user>     <user address="shenzhen">         <name>华仔</name>         <age>28</age>         <social>             <email>huazai@163.com</email>             <mobile>1238655464</mobile>         </social>     </user> </users> 

解析xml文件 address,attr意味着该address字段是一个XML属性而不是一个嵌套元素。如果结构体有一个名为 XMLName 的 Name 类型的云服务器字段,Unmarshal 在该字段中记录元素名称。

为了正确解析,go 语言的 xml 包要求 struct 定义中的所有字段必须是可导出的(即首字母大写)

package main import (  "encoding/xml"  "fmt"  "io/ioutil"  "os" ) func main() {   xmlFile,err:=os.Open("users.xml")  if err!=nil {    fmt.Println(err)  }  fmt.Println("successfully opened users.xml")  defer xmlFile.Close()  byteValue,_:=ioutil.ReadAll(xmlFile)  var users Users  xml.Unmarshal(byteValue,&users)  for i :=0;i<len(users.Users);i++ {    fmt.Println("User Address: "+users.Users[i].Address)   fmt.Println("User Name: "+users.Users[i].Name)   fmt.Println("Facebook Url: "+users.Users[i].Social.Email)  } } type Users struct {   XMLName xml.Name `xml:"users"`  Users []User `xml:"user"` } type User struct {   XMLName xml.Name `xml:"user"`  Address string `xml:"address,attr"`  Name string `xml:"name"`  Social Social `xml:"social"` } type Social struct {   XMLName xml.Name `xml:"social"`  Mobile string `xml:"mobile"`  Email string `xml:"email"` } 

输出结果如下:

successfully opened users.xml User Address: beijing User Name: wanger Facebook Url: wanger@163.com User Address: chengdu User Name: 冬哥 Facebook Url: dongge@163.com User Address: chengdu User Name: 夏老师 Facebook Url: xialaoshi@163.com User Address: beijing User Name: 郑哥 Facebook Url: zhengge@163.com User Address: shanghai User Name: 姜总 Facebook Url: jiangzong@163.com User Address: chongqing User Name: 乔克 Facebook Url: qiaoke@163.com User Address: shenzhen User Name: 华仔 Facebook Url: huazai@163.com 

生成xml文件

func Marshal(v interface{ }) ([]byte, error) func MarshalIndent(v interface{ }, prefix, indent string) ([]byte, error) 

可以使用Marshal()函数和MarshalIndent()函数,之前的json和yaml包里也有用到,区别就是MarshalIndent()可以添加 前缀和缩进,看起来更美观一点,Marshal 和MarshalIndent通过编写一个或多个包含数据的 XML 元素来处理所有其他数据。

package main import (  "encoding/xml"  "fmt"  "io/ioutil" ) func main() {   wanger:=User{ Address:"beijing",Name:"wanger",Age:24,Social:Social{ Email:"wanger@163.com",Mobile:"111111111111"}}  huazi:=User{ Address:"shenzhen",Name:"huazai",Age:28,Social:Social{ Email:"huazai@163.com",Mobile:"111122211111"}}  qiaoke:=User{ Address:"chongqing",Name:"qiaoke",Age:30,Social:Social{ Email:"qiaoke@163.com",Mobile:"13332211111"}}  xialaoshi:=User{ Address:"chengdu",Name:"夏老师",Age:29,Social:Social{ Email:"xialaoshi@163.com",Mobile:"11144445411111"}}  jiangzong:=User{ Address:"shanghai",Name:"姜总",Age:25,Social:Social{ Email:"jiangzong@163.com",Mobile:"111222445211111"}}  dongdong:=User{ Address:"chengdu",Name:"冬哥",Age:30,Social:Social{ Email:"dongdong@163.com",Mobile:"1155555211111"}}  zhengge:=User{ Address:"beijing",Name:"郑哥",Age:24,Social:Social{ Email:"zhengge@163.com",Mobile:"1112224566211111"}}     v:=&Users{ Users: []User{ wanger,huazi,qiaoke,xialaoshi,zhengge,jiangzong,dongdong}}  result, err := xml.MarshalIndent(v, "  ", "    ")  if err != nil {    fmt.Printf("error: %v\n", err)  }  fmt.Println(string(result))  fileName := "users.xml"  err = ioutil.WriteFile(fileName, result, 0644)  if err != nil {    panic("Unable to write data into the file")  } } type Users struct {   XMLName xml.Name `xml:"users"`  Users []User `xml:"user"` } type User struct {   XMLName xml.Name `xml:"user"`  Age int64 `xml:"age"`  Address string `xml:"address,attr"`  Name string `xml:"name"`  Social Social `xml:"social"` } type Social struct {   XMLName xml.Name `xml:"social"`  Mobile string `xml:"mobile"`  Email string `xml:"email"` } 

输出信息如下

<users>      <user address="beijing">          <age>24</age>          <name>wanger</name>          <social>              <mobile>111111111111</mobile>              <email>wanger@163.com</email>          </social>      </user>      <user address="shenzhen">          <age>28</age>          <name>huazai</name>          <social>              <mobile>111122211111</mobile>              <email>huazai@163.com</email>          </social>      </user>      <user address="chongqing">          <age>30</age>          <name>qiaoke</name>          <social>              <mobile>13332211111</mobile>              <email>qiaoke@163.com</email>          </social>      </user>      <user address="chengdu">          <age>29</age>          <name>夏老师</name>          <social>              <mobile>11144445411111</mobile>              <email>xialaoshi@163.com</email>          </social>      </user>      <user address="beijing">          <age>24</age>          <name>郑哥</name>          <social>              <mobile>1112224566211111</mobile>              <email>zhengge@163.com</email>          </social>      </user>      <user address="shanghai">          <age>25</age>          <name>姜总</name>          <social>              <mobile>111222445211111</mobile>              <email>jiangzong@163.com</email>          </social>      </user>      <user address="chengdu">          <age>30</age>          <name>冬哥</name>          <social>              <mobile>1155555211111</mobile>              <email>dongdong@163.com</email>          </social>      </user>  </users> 

文中所有代码已同步到我们的github组织sunsharing-note可阅读原文访问

滇ICP备2023000592号-31