var newStu Student
//反序列化
err1 := xml.Unmarshal(buf, &newStu)
if err1 != nil{
fmt.Println(err1.Error())
return
fmt.Println("newStu: ", newStu)
NewEncoder
func NewEncoder(w io.Writer) Encoder
NewEncoder创建一个写入w的Encoder。
(*Encoder) Encode
func (enc *Encoder) Encode(v interface{}) error
Encode将v编码为XML后写入底层。
NewDecoder
func NewDecoder(r io.Reader) *Decoder
创建一个从r读取XML数据的解析器。如果r未实现io.ByteReader接口,NewDecoder会为其添加缓存。
(*Decoder) Decode
func (d *Decoder) Decode(v interface{}) error
Decode方法功能类似xml.Unmarshal函数,但会从底层读取XML数据并查找StartElement。
package main
import (
"fmt"
"encoding/xml"
type Address struct{
City string
Area string
type Email struct{
Where string xml:"where,attr"
Addr string
type Student struct{
Id int xml:"id,attr"
Address
Email []Email
FirstName string xml:"name>first"
LastName string xml:"name>last"
func main(){
func t2(){
f, err := os.Create("d:/myxml.xml")
if err != nil{
fmt.Println("err: ", err.Error())
return
defer f.Close()
//实例化对象
stu := Student{23, Address{"shanghai","pudong"},[]Email{Email{"home","home@qq.com"}, Email{"work","work@qq.com"}},"chain","zhang"}
fmt.Println("stu: ", stu)
//序列化到文件中
encoder := xml.NewEncoder(f)
err1 := encoder.Encode(stu)
if err1 != nil{
fmt.Println("err1: ", err1.Error())
return
//重置文件指针
f.Seek(0, os.SEEK_SET)
var newStu Student
//反序列化到newStu对象
decoder := xml.NewDecoder(f)
err2 := decoder.Decode(&newStu)
if err2 != nil{
fmt.Println("err2: ", err2.Error())
return
fmt.Println("new stu: ", newStu)
Token
处了上面的方法,xml包还提供了其他的解析xml方法。在.net,java中都提供了XMLReader类来解析xml,在go中也有类似的方法。
(*Decoder) Token
func (d *Decoder) Token() (t Token, err error)Token
返回输入流里的下一个XML token。在输入流的结尾处,会返回(nil, io.EOF)
返回的token数据里的[]byte数据引用自解析器内部的缓存,只在下一次调用Token之前有效。如要获取切片的拷贝,调用CopyToken函数或者token的Copy方法。
成功调用的Token方法会将自我闭合的元素(如
)扩展为分离的起始和结束标签。
Token方法会保证它返回的StartElement和EndElement两种token正确的嵌套和匹配:如果本方法遇到了不正确的结束标签,会返回一个错误。
我们看下面的例子
package main
import (
"fmt"
"encoding/xml"
type Address struct{
City string
Area string
type Email struct{
Where string xml:"where,attr"
Addr string
type Student struct{
Id int xml:"id,attr"
Address
Email []Email
FirstName string xml:"name>first"
LastName string xml:"name>last"
func main(){
XmlT3()
func XmlT3(){
f, err := os.Create("d:/myxml.xml")
if err != nil{
fmt.Println("err: ", err.Error())
return
defer f.Close()
//实例化对象
stu := Student{23, Address{"shanghai","pudong"},[]Email{Email{"home","home@qq.com"}, Email{"work","work@qq.com"}},"chain","zhang"}
fmt.Println("stu: ", stu)
//序列化到文件中
encoder := xml.NewEncoder(f)
err1 := encoder.Encode(stu)
if err1 != nil{
fmt.Println("err1: ", err1.Error())
return
//重置文件指针
f.Seek(0, os.SEEK_SET)
decoder := xml.NewDecoder(f)
var strName string
token, err2 := decoder.Token()
if err2 != nil{
break
switch t := token.(type){
case xml.StartElement:
stelm := xml.StartElement(t)
fmt.Println("start: ", stelm.Name.Local)
strName = stelm.Name.Local
case xml.EndElement:
endelm := xml.EndElement(t)
fmt.Println("end: ", endelm.Name.Local)
case xml.CharData:
data := xml.CharData(t)
str := string(data)
switch strName{
case "City":
fmt.Println("city:", str)
case "first":
fmt.Println("first: ", str)
上面这几种方法,Token解析是最快的。对于大文件解析,对于性能要求高时,这种方式是最好的选择
package
import "encoding/json"
Marshal
func Marshal(v interface{}) ([]byte, error)
Marshal函数返回v的json编码。
Marshal函数会递归的处理值。如果一个值实现了Marshaler接口切非nil指针,会调用其MarshalJSON方法来生成json编码。nil指针异常并不是严格必需的,但会模拟与UnmarshalJSON的行为类似的必需的异常。
否则,Marshal函数使用下面的基于类型的默认编码格式:
布尔类型编码为json布尔类型。
浮点数、整数和Number类型的值编码为json数字类型。
字符串编码为json字符串。角括号"<"和">"会转义为"\u003c"和"\u003e"以避免某些浏览器吧json输出错误理解为HTML。基于同样的原因,"&"转义为"\u0026"。
数组和切片类型的值编码为json数组,但[]byte编码为base64编码字符串,nil切片编码为null。
Unmarshal
func Unmarshal(data []byte, v interface{}) error
Unmarshal函数解析json编码的数据并将结果存入v指向的值。
Unmarshal和Marshal做相反的操作,必要时申请映射、切片或指针,有如下的附加规则:
要将json数据解码写入一个指针,Unmarshal函数首先处理json数据是json字面值null的情况。此时,函数将指针设为nil;否则,函数将json数据解码写入指针指向的值;如果指针本身是nil,函数会先申请一个值并使指针指向它。
要将json数据解码写入一个结构体,函数会匹配输入对象的键和Marshal使用的键(结构体字段名或者它的标签指定的键名),优先选择精确的匹配,但也接受大小写不敏感的匹配。
要将json数据解码写入一个接口类型值,函数会将数据解码为如下类型写入接口:
Bool 对应JSON布尔类型
float64 对应JSON数字类型
string 对应JSON字符串类型
[]interface{} 对应JSON数组
map[string]interface{} 对应JSON对象
nil 对应JSON的null
如果一个JSON值不匹配给出的目标类型,或者如果一个json数字写入目标类型时溢出,Unmarshal函数会跳过该字段并尽量完成其余的解码操作。如果没有出现更加严重的错误,本函数会返回一个描述第一个此类错误的详细信息的UnmarshalTypeError。
JSON的null值解码为go的接口、指针、切片时会将它们设为nil,因为null在json里一般表示“不存在”。 解码json的null值到其他go类型时,不会造成任何改变,也不会产生错误。
当解码字符串时,不合法的utf-8或utf-16代理(字符)对不视为错误,而是将非法字符替换为unicode字符U+FFFD。
package main
import (
"fmt"
"encoding/json"
type Address struct{
City string json:"ciry"
Area string json:"area"
type Email struct{
Where string json:"where"
Addr string json:"addr"
type Student struct{
Id int json:"id"
Address json:"address"
Emails []Email json:"emails"
FirstName string json:"first_name"
LastName string json:"last_name"
func main(){
JsonT1()
func JsonT1(){
//实例化对象
stu := Student{23, Address{"shanghai","pudong"},[]Email{Email{"home","home@qq.com"}, Email{"work","work@qq.com"}},"chain","zhang"}
fmt.Println("stu: ", stu)
//序列化对象到字符串
buf, err1 := json.Marshal(stu)
if err1 != nil{
fmt.Println("err1: ", err1.Error())
return
fmt.Println("json: ", string(buf))
//反序列化字符串到对象
var newStu Student
err2 := json.Unmarshal(buf, &newStu)
if err2 != nil{
fmt.Println("err2: ", err2.Error())
return
fmt.Println("new stu: ", newStu)
NewEncoder
func NewEncoder(w io.Writer) Encoder
NewEncoder创建一个将数据写入w的Encoder。
(*Encoder) Encode
func (enc *Encoder) Encode(v interface{}) error
Encode将v的json编码写入输出流,并会写入一个换行符。
NewDecoder
func NewDecoder(r io.Reader) Decoder
NewDecoder创建一个从r读取并解码json对象的Decoder,解码器有自己的缓冲,并可能超前读取部分json数据。
(*Decoder) Decode
func (dec *Decoder) Decode(v interface{}) error
Decode从输入流读取下一个json编码值并保存在v指向的值里。
package main
import (
"fmt"
"encoding/json"
type Address struct{
City string json:"ciry"
Area string json:"area"
type Email struct{
Where string json:"where"
Addr string json:"addr"
type Student struct{
Id int json:"id"
Address json:"address"
Emails []Email json:"emails"
FirstName string json:"first_name"
LastName string json:"last_name"
func main(){
JsonT2()
func JsonT2(){
f, err1 := os.Create("d:/myjson.txt")
if err1 != nil{
fmt.Println("err1: ", err1.Error())
return
defer f.Close()
//实例化对象
stu := Student{23, Address{"shanghai","pudong"},[]Email{Email{"home","home@qq.com"}, Email{"work","work@qq.com"}},"chain","zhang"}
fmt.Println("stu: ", stu)
//序列化
encoder := json.NewEncoder(f)
err2 := encoder.Encode(stu)
if err2 != nil{
fmt.Println("err2: ", err2.Error)
return
//重置文件指针
f.Seek(0, os.SEEK_SET)
var newStu Student
//反序列化
decoder := json.NewDecoder(f)
err3 := decoder.Decode(&newStu)
if err3 != nil{
fmt.Println("err3: ", err3.Error())
return
fmt.Println("new stu: ", newStu)
文件保存内容
作者:ChainZhang
链接:https://www.jianshu.com/p/283eee583339
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
🏁Eric