go 操作xml 和 json

红太狼 2022-05-20 05:15 524阅读 0赞

go 操作xml 和 json 分别使用 encoding/xml 和 encoding/json 来实现 下面我们通过代码来讲解一下go 操作xml 文件 和 json 格式数据

读取xml

假设我有一个xml 文件如下
C:\\Users\\admin\\go\\src\\html\\mgr.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <servers version="1">
  3. <server>
  4. <serverName>Shanghai_VPN</serverName>
  5. <serverIP>127.0.0.1</serverIP>
  6. </server>
  7. <server>
  8. <serverName>Beijing_VPN</serverName>
  9. <serverIP>127.0.0.2</serverIP>
  10. </server>
  11. <database>
  12. <databaseName>Oracle</databaseName>
  13. <databasePort>1521</databasePort>
  14. </database>
  15. <database>
  16. <databaseName>MySQL</databaseName>
  17. <databasePort>3306</databasePort>
  18. </database>
  19. </servers>

现在我们需要取出其中的数据 我们需要定义结构体 定义我们需要拿到xml的哪些标签,例如我现在想拿到server 标签和 database 标签里面的数据那我就需要为这两个标签分别定义两个结构体

为元素定义结构体

  1. // server 标签
  2. type servers struct {
  3. XMLName xml.Name `xml:"server"`
  4. ServerName string `xml:"serverName"`
  5. ServerIP string `xml:"serverIP"`
  6. }
  7. // database 标签
  8. type database struct {
  9. XMLName xml.Name `xml:"database"`
  10. DatabaseName string `xml:"databaseName"`
  11. DatabasePort int `xml:"databasePort"`
  12. }
  13. // 整个xml 文件 里面包含了 server 和 database 标签
  14. type XmlData struct {
  15. XmlName xml.Name `xml:"servers"`
  16. Version string `xml:"version,attr"`
  17. Servers []servers `xml:"server"`
  18. Database []database `xml:"database"`
  19. Desc string `xml:",innerxml"`
  20. }

这里需要注意几点1. 结构体的字段必须是可导出的 2.tag 必须和xml 里面的元素名称一样,也就是 xml:"xx" 这个地方 定义的tag 和 xml 元素名称不一样或者说大小写不一样都会导致xml 元素解析不出来,例如我的xml:"databasePort" 这个databasePort 必须和 xml 里面的标签一样的名称

完整代码demo

  1. package growth
  2. // 学习go 第十四天 学习使用go io操作
  3. import (
  4. "fmt"
  5. "os"
  6. "io/ioutil"
  7. "path/filepath"
  8. "encoding/xml"
  9. )
  10. func Day14IO() {
  11. currentPath, _ := filepath.Abs(os.Args[0])
  12. fmt.Println(currentPath)
  13. // 打开并读取文件
  14. data, err:= ioutil.ReadFile("C:\\Users\\admin\\go\\情绪.jpg")
  15. if err != nil {
  16. fmt.Println(err)
  17. }
  18. fmt.Println(string(data))
  19. }
  20. func Day14Xml() {
  21. // 学习使用go 处理xml, go 使用xml.Unmarshal(data []byte, v interface{}) error 来处理xml文件
  22. /*
  23. 我们需要定义结构体来获取我们需要解析的xml标签
  24. Unmarshal解析的时候XML元素和struct字段怎么对应起来的呢?
  25. 这是有一个优先级读取流程的,首先会读取struct tag,也就是 `xml:"xx"` 这个地方
  26. 如果没有,那么就会对应字段名。必须注意一点的是解析的时候tag、
  27. 字段名、XML元素都是大小写敏感的,所以必须一一对应字段
  28. 解析XML到struct的时候遵循如下的规则:
  29. 1. 如果struct的一个字段是string或者[]byte类型且它的tag
  30. 含有",innerxml",Unmarshal将会将此字段所对应的元素内所有内嵌的原始xml
  31. 累加到此字段上,如上面例子Description定义。最后的输出是
  32. 2. 如果struct中有一个叫做XMLName,且类型为xml.Name字段,
  33. 那么在解析的时候就会保存这个element的名字到该字段,如上面例子中的servers。
  34. 3. 如果某个struct字段的tag定义中含有XML结构中element的名称,
  35. 那么解析的时候就会把相应的element值赋值给该字段,
  36. 如上servername和serverip定义
  37. 4. 如果某个struct字段的tag定义了中含有",attr",
  38. 那么解析的时候就会将该结构所对应的element的与字段同名的
  39. 属性的值赋值给该字段,如上version定义
  40. 5. 如果某个struct字段的tag定义了"-",那么不会为该字段解析匹配任何xml数据
  41. 6. 如果struct字段后面的tag定义了",any",如果他的子元素在不满足其他的规则的时候就会匹配到这个字段
  42. */
  43. type servers struct {
  44. XMLName xml.Name `xml:"server"`
  45. ServerName string `xml:"serverName"`
  46. ServerIP string `xml:"serverIP"`
  47. }
  48. type database struct {
  49. XMLName xml.Name `xml:"database"`
  50. DatabaseName string `xml:"databaseName"`
  51. DatabasePort int `xml:"databasePort"`
  52. }
  53. type XmlData struct {
  54. XmlName xml.Name `xml:"servers"`
  55. Version string `xml:"version,attr"`
  56. Servers []servers `xml:"server"`
  57. Database []database `xml:"database"`
  58. Desc string `xml:",innerxml"`
  59. }
  60. filename := "C:\\Users\\admin\\go\\src\\html\\mgr.xml"
  61. file , err := os.Open(filename)
  62. if err != nil {
  63. fmt.Println("Open File err", err)
  64. return
  65. }
  66. defer file.Close()
  67. // 读取xml 文件
  68. data, e1 := ioutil.ReadAll(file)
  69. if e1 != nil {
  70. fmt.Println("Read File Err", err)
  71. return
  72. }
  73. properties := &XmlData{}
  74. // 通过xml.Umarshal 解析xml
  75. e2 := xml.Unmarshal(data, properties)
  76. if e2 != nil {
  77. fmt.Println(e2)
  78. return
  79. }
  80. fmt.Println(properties.Servers[0].ServerIP)
  81. fmt.Println(properties.Servers[0].ServerName)
  82. fmt.Println(properties.Database[0].DatabaseName)
  83. fmt.Println(properties.Database[0].DatabasePort)
  84. fmt.Println(properties.Database[1].DatabaseName)
  85. fmt.Println(properties.Database[1].DatabasePort)
  86. }

读取json

现在假如我们有这样一个json 数据

{"ip": "192.168.1.100", "port": 1521, "nums": [1, 2, 3], "relation": {"mykey": "myval"}}

我们想拿到里面全部的key-value

go 解析json 同样需要定义结构体

为这个json 定义结构体

  1. type data struct {
  2. // 结构体里面的字段必须是可导出的(大写字母开头)
  3. // 且字段名要和json 里面key的名称一样
  4. Ip string
  5. Port int
  6. Nums []int
  7. Relation map[string]string
  8. }
  9. 然后使用 json.Unmarshal来解析

完整的代码demo

  1. package growth
  2. // 学习go 第十六天 学习使用go 操作json
  3. import (
  4. "fmt"
  5. "encoding/json"
  6. )
  7. type data struct {
  8. // 结构体里面的字段必须是可导出的(大写字母开头)
  9. // 且字段名要和json 里面key的名称一样
  10. Ip string
  11. Port int
  12. Nums []int
  13. Relation map[string]string
  14. }
  15. func Day16Json() {
  16. /*
  17. 在解析的时候,如何将json数据与struct字段相匹配呢?
  18. 例如JSON的key是Foo,那么怎么找对应的字段呢?
  19. 首先查找tag含有Foo的可导出的struct字段(首字母大写)
  20. 其次查找字段名是Foo的导出字段
  21. 最后查找类似FOO或者FoO这样的除了首字母之外其他大小写不敏感的
  22. 导出字段
  23. */
  24. var loads data
  25. js := []byte(`{"ip": "192.168.1.100", "port": 1521, "nums": [1, 2, 3], "relation": {"mykey": "myval"}}`)
  26. // 解析json
  27. err := json.Unmarshal(js, &loads)
  28. if err != nil {
  29. fmt.Println("Unmarshal Err", err)
  30. return
  31. }
  32. fmt.Println(loads)
  33. // 生成json, 假如我们需要生成像上面一样的json 需要通过json.Marshal 方法, 我们需要Marshal的对象还是结构体
  34. var dumps data
  35. dumps.Ip = "127.0.0.1"
  36. dumps.Port = 3306
  37. dumps.Nums = []int {1, 2, 3}
  38. dumps.Relation = map[string]string{"key": "value"}
  39. // Marshal 之后返回的是byte 类型的数组[]byte
  40. dump, e2 := json.Marshal(dumps)
  41. if e2 != nil {
  42. fmt.Println("Marshal Err", e2)
  43. return
  44. }
  45. // dump 是 byte 类型的数组
  46. fmt.Println(dump)
  47. // 转换为string就可以看到json
  48. fmt.Println(string(dump))
  49. }

json 数据写入文件

将json 写入文件需要使用 NewEncoder 函数,创建一个文件,然后将结构体数据 Encode 到文件中

  1. type ServerData struct {
  2. Ip string `json:"ip"`
  3. Port int `json:"port"`
  4. ServerList []string `json:"serverList"`
  5. }
  6. type Server struct {
  7. Data ServerData `json:"data"`
  8. Code int `json:"code"`
  9. }
  10. // json 写入文件
  11. func Json2File() {
  12. fd, err := os.Create("data.json")
  13. defer fd.Close()
  14. if err != nil {
  15. fmt.Println("create json fail")
  16. return
  17. }
  18. var server Server
  19. server.Code = 0
  20. server.Data.Ip = "192.168.30.151"
  21. server.Data.Port = 1521
  22. server.Data.ServerList = []string{"nginx", "mysql"}
  23. encoder := json.NewEncoder(fd)
  24. err2 := encoder.Encode(server)
  25. if err2 != nil {
  26. fmt.Println("encode failed")
  27. }
  28. }

从文件中加载json数据

从文件中加载json 需要使用 NewDecoder 然后使用Decode函数decode 到结构体里面

  1. type ServerData struct {
  2. Ip string `json:"ip"`
  3. Port int `json:"port"`
  4. ServerList []string `json:"serverList"`
  5. }
  6. type Server struct {
  7. Data ServerData `json:"data"`
  8. Code int `json:"code"`
  9. }
  10. // 从文件中读取出json, 解析到结构体
  11. func File2Json() {
  12. var server Server
  13. fd, _ := os.Open("data.json")
  14. defer fd.Close()
  15. decoder := json.NewDecoder(fd)
  16. err := decoder.Decode(&server)
  17. if err != nil {
  18. fmt.Println("decode fail", err)
  19. } else {
  20. fmt.Println("decode data", server)
  21. }
  22. }

发表评论

表情:
评论列表 (有 0 条评论,524人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JSONXML

    JSON JSON(JavaScript Object Notation)一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。可在不同平台之间进行数据交换。JSO

    相关 SpringBoot返回jsonxml

    有些情况接口需要返回的是xml数据,在springboot中并不需要每次都转换一下数据格式,只需做一些微调整即可。 新建一个springboot项目,加入依赖jackson-