go 操作xml 和 json

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

读取xml

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

<?xml version="1.0" encoding="utf-8"?>
<servers version="1">
    <server>
        <serverName>Shanghai_VPN</serverName>
        <serverIP>127.0.0.1</serverIP>
    </server>
    <server>
        <serverName>Beijing_VPN</serverName>
        <serverIP>127.0.0.2</serverIP>
    </server>
    <database>
        <databaseName>Oracle</databaseName>
        <databasePort>1521</databasePort>
    </database>
    <database>
        <databaseName>MySQL</databaseName>
        <databasePort>3306</databasePort>
    </database>
</servers>

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

为元素定义结构体

// server 标签
type servers struct {
		XMLName xml.Name `xml:"server"`
		ServerName string `xml:"serverName"`
		ServerIP string `xml:"serverIP"`
	}
// database 标签
type database struct {
	XMLName xml.Name `xml:"database"`
	DatabaseName string `xml:"databaseName"`
	DatabasePort int `xml:"databasePort"`
}
// 整个xml 文件 里面包含了 server 和 database 标签
type XmlData struct {
		XmlName xml.Name `xml:"servers"`
		Version string  `xml:"version,attr"`
		Servers []servers `xml:"server"`
		Database []database `xml:"database"`
		Desc string `xml:",innerxml"`
	}

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

完整代码demo

package growth

// 学习go 第十四天 学习使用go io操作

import (
	"fmt"
	"os"
	"io/ioutil"
	"path/filepath"
	"encoding/xml"

)

func Day14IO()  {

	currentPath, _ := filepath.Abs(os.Args[0])
	fmt.Println(currentPath)
	// 打开并读取文件
	data, err:= ioutil.ReadFile("C:\\Users\\admin\\go\\情绪.jpg")
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(string(data))
}

func Day14Xml()  {
	// 学习使用go 处理xml, go 使用xml.Unmarshal(data []byte, v interface{}) error 来处理xml文件
	/*
	我们需要定义结构体来获取我们需要解析的xml标签
	Unmarshal解析的时候XML元素和struct字段怎么对应起来的呢?
	这是有一个优先级读取流程的,首先会读取struct tag,也就是 `xml:"xx"` 这个地方
	如果没有,那么就会对应字段名。必须注意一点的是解析的时候tag、
	字段名、XML元素都是大小写敏感的,所以必须一一对应字段

	解析XML到struct的时候遵循如下的规则:

	1. 如果struct的一个字段是string或者[]byte类型且它的tag
	含有",innerxml",Unmarshal将会将此字段所对应的元素内所有内嵌的原始xml
	累加到此字段上,如上面例子Description定义。最后的输出是
	2. 如果struct中有一个叫做XMLName,且类型为xml.Name字段,
	那么在解析的时候就会保存这个element的名字到该字段,如上面例子中的servers。
	3. 如果某个struct字段的tag定义中含有XML结构中element的名称,
	那么解析的时候就会把相应的element值赋值给该字段,
	如上servername和serverip定义
	4. 如果某个struct字段的tag定义了中含有",attr",
	那么解析的时候就会将该结构所对应的element的与字段同名的
	属性的值赋值给该字段,如上version定义
	5. 如果某个struct字段的tag定义了"-",那么不会为该字段解析匹配任何xml数据
	6. 如果struct字段后面的tag定义了",any",如果他的子元素在不满足其他的规则的时候就会匹配到这个字段
	 */

	type servers struct {
		XMLName xml.Name `xml:"server"`
		ServerName string `xml:"serverName"`
		ServerIP string `xml:"serverIP"`
	}

	type database struct {
		XMLName xml.Name `xml:"database"`
		DatabaseName string `xml:"databaseName"`
		DatabasePort int `xml:"databasePort"`
	}

	type XmlData struct {
		XmlName xml.Name `xml:"servers"`
		Version string  `xml:"version,attr"`
		Servers []servers `xml:"server"`
		Database []database `xml:"database"`
		Desc string `xml:",innerxml"`
	}
	filename := "C:\\Users\\admin\\go\\src\\html\\mgr.xml"
	file , err := os.Open(filename)

	if err != nil {
		fmt.Println("Open File err", err)
		return
	}

	defer file.Close()
	// 读取xml 文件
	data, e1 := ioutil.ReadAll(file)
	if e1 != nil {
		fmt.Println("Read File Err", err)
		return
	}
	properties := &XmlData{}
	// 通过xml.Umarshal 解析xml
	e2 := xml.Unmarshal(data, properties)

	if e2 != nil {
		fmt.Println(e2)
		return
	}
	fmt.Println(properties.Servers[0].ServerIP)
	fmt.Println(properties.Servers[0].ServerName)
	fmt.Println(properties.Database[0].DatabaseName)
	fmt.Println(properties.Database[0].DatabasePort)
	fmt.Println(properties.Database[1].DatabaseName)
	fmt.Println(properties.Database[1].DatabasePort)

}

读取json

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

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

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

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

为这个json 定义结构体

type data struct {
	// 结构体里面的字段必须是可导出的(大写字母开头)
	// 且字段名要和json 里面key的名称一样
	Ip string
	Port int
	Nums []int
	Relation map[string]string

}

然后使用 json.Unmarshal来解析

完整的代码demo


package growth

// 学习go 第十六天 学习使用go 操作json

import (
	"fmt"
	"encoding/json"
)

type data struct {
	// 结构体里面的字段必须是可导出的(大写字母开头)
	// 且字段名要和json 里面key的名称一样
	Ip string
	Port int
	Nums []int
	Relation map[string]string

}



func Day16Json() {

	/*
	在解析的时候,如何将json数据与struct字段相匹配呢?
	例如JSON的key是Foo,那么怎么找对应的字段呢?
    首先查找tag含有Foo的可导出的struct字段(首字母大写)
    其次查找字段名是Foo的导出字段
    最后查找类似FOO或者FoO这样的除了首字母之外其他大小写不敏感的
	导出字段

	 */
	var loads data
	js := []byte(`{"ip": "192.168.1.100", "port": 1521, "nums": [1, 2, 3], "relation": {"mykey": "myval"}}`)
	// 解析json
	err := json.Unmarshal(js, &loads)

	if err != nil {
		fmt.Println("Unmarshal Err", err)
		return
	}

	fmt.Println(loads)

	// 生成json, 假如我们需要生成像上面一样的json 需要通过json.Marshal 方法, 我们需要Marshal的对象还是结构体

	var dumps data
	dumps.Ip = "127.0.0.1"
	dumps.Port = 3306
	dumps.Nums = []int {1, 2, 3}
	dumps.Relation = map[string]string{"key": "value"}
	// Marshal 之后返回的是byte 类型的数组[]byte
	dump, e2 := json.Marshal(dumps)

	if e2 != nil {
		fmt.Println("Marshal Err", e2)
		return
	}
	// dump 是 byte 类型的数组
	fmt.Println(dump)
	// 转换为string就可以看到json
	fmt.Println(string(dump))

}


json 数据写入文件

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

type ServerData struct {
	Ip         string   `json:"ip"`
	Port       int      `json:"port"`
	ServerList []string `json:"serverList"`
}

type Server struct {
	Data ServerData `json:"data"`
	Code int        `json:"code"`
}

// json 写入文件
func Json2File() {
	fd, err := os.Create("data.json")

	defer fd.Close()

	if err != nil {
		fmt.Println("create json fail")
		return
	}
	var server Server
	server.Code = 0
	server.Data.Ip = "192.168.30.151"
	server.Data.Port = 1521
	server.Data.ServerList = []string{"nginx", "mysql"}
	encoder := json.NewEncoder(fd)
	err2 := encoder.Encode(server)

	if err2 != nil {
		fmt.Println("encode failed")
	}

}

从文件中加载json数据

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

type ServerData struct {
	Ip         string   `json:"ip"`
	Port       int      `json:"port"`
	ServerList []string `json:"serverList"`
}

type Server struct {
	Data ServerData `json:"data"`
	Code int        `json:"code"`
}

// 从文件中读取出json, 解析到结构体
func File2Json() {
	var server Server
	fd, _ := os.Open("data.json")

	defer fd.Close()

	decoder := json.NewDecoder(fd)

	err := decoder.Decode(&server)

	if err != nil {
		fmt.Println("decode fail", err)
	} else {
		fmt.Println("decode data", server)
	}

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值