大家好,我是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 mainimport ( "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 mainimport ( "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 mainimport ( "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.jsonUser Type: beijingUser Age: 24User Name: wangerUser Email: wanger@163.comUser Type: chengduUser Age: 30User Name: dongdongUser Email: User Type: chengduUser Age: 28User Name: 夏老师User Email: User Type: beijingUser Age: 30User Name: 郑哥User Email: zhengge@163.comUser Type: shanghaiUser Age: 25User Name: 姜总User Email: jaingzong@163.comUser Type: chongqingUser Age: 29User Name: 乔克User Email: qiaoke@163.comUser Type: shenzhenUser Age: 28User 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 mainimport ( "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 mainimport ( "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.xmlUser Address: beijingUser Name: wangerFacebook Url: wanger@163.comUser Address: chengduUser Name: 冬哥Facebook Url: dongge@163.comUser Address: chengduUser Name: 夏老师Facebook Url: xialaoshi@163.comUser Address: beijingUser Name: 郑哥Facebook Url: zhengge@163.comUser Address: shanghaiUser Name: 姜总Facebook Url: jiangzong@163.comUser Address: chongqingUser Name: 乔克Facebook Url: qiaoke@163.comUser Address: shenzhenUser 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 mainimport ( "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可阅读原文访问


最后,求关注。如果你还想看更多优质原创文章,欢迎关注我们的公众号「运维开发故事」。

我是 wanger,《运维开发故事》公众号团队中的一员,一线运维农民工,云原生实践者,这里不仅有硬核的技术干货,还有我们对技术的思考和感悟,欢迎关注我们的公众号,期待和你一起成长!