《Go语言从入门到精通》Go语言中数据格式的分析与转换_第1页
《Go语言从入门到精通》Go语言中数据格式的分析与转换_第2页
《Go语言从入门到精通》Go语言中数据格式的分析与转换_第3页
《Go语言从入门到精通》Go语言中数据格式的分析与转换_第4页
《Go语言从入门到精通》Go语言中数据格式的分析与转换_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Go语言中数据格式的分析与转换Go语言从入门到精通了解编程中常用的数据交换格式掌握Go语言中JSON格式数据的分析与处理01FORMAT02XML03JSONtarget目标掌握Go语言中XML格式数据的分析与处理目录导航10.1常见的数据交换格式Contents数据交换格式在不同的计算机之间、应用程序之间,通过文件、网络等各种途径进行信息交换时,为了双方都能够理解而制定的数据格式。

数据交换格式的基本要求是能够跨平台、跨语言得到准确无误的理解常见的数据交换格式纯文本

CSV

XML

JSON(及各种变体)YAMLProtoBuf目录导航10.2XML格式的处理ContentsXML格式

XML是可扩展标记语言(EXtensibleMarkupLanguage)的缩写简称,它被设计为专注于数据的表达而非其他(例如数据的显示样式等)方面,因此特别适合也主要被应用于传输数据和存储数据XML格式XML格式是基于文本格式之上的,因此,XML文件就是纯文本文件的一种。XML文件可以直接用文本编辑软件打开,其中内容也都是由人可以识别的字符组成的。XML数据在程序中的表现形式就是一个字符串XML对文本进行了更高级别的格式要求,以便能够用一定的文本格式规范来表现出各种类型的数据类型和数据结构,能够支持复杂的数据类型并且能对数据的取值范围等做出更具体的规定和限制将数据序列化成XML格式引用encoding/xml包//

Person

准备进行XML序列化的表示个人信息的数据结构类型type

Person

struct

{

XMLName

xml.Name

`xml:"person"`

Name

string

`xml:"name"`

ID

string

`xml:"id,attr"`

Age

int

`xml:"age"`

Married

bool

Phone

string

`xml:"phone,omitempty"`

Mobile

[]string

`xml:"mobiles>mobile"`

height

float64

`xml:"height"`

AddressType

SecondAddress

AddressType

`xml:"secondAddress"`

Remark

string

`xml:",comment"`}

准备数据结构用到的嵌套数据结构//

AddressType

表示个人住址的数据结构type

AddressType

struct

{

State

string

City

string

Detail

string

PostalCode

string

`xml:"postalCode,attr"`

remark

string}常见类型无需标注进行XML序列化(编码)person1

:=

&Person{Name:

"张三",

ID:

,

Age:

25,

Married:

false,

Mobile:

[]string{,

},

height:

170,

AddressType:

AddressType{State:

"中国",

City:

"北京",

Detail:

"海淀区中关村1号",

PostalCode:

"100099",

remark:

"路口右转"},

SecondAddress:

AddressType{State:

"中国",

City:

"上海",

Detail:

"徐汇区南京路1号",

PostalCode:

"210001",

remark:

"无"},

Remark:

"信息有待完善"}

var

strT

strings.BuilderencoderT

:=

xml.NewEncoder(&strT)errT

:=

encoderT.Encode(person1)if

errT

!=

nil

{

t.Printfln("XML编码时发生错误:%v",

errT.Error())

return}t.Printfln("XML字符串为:%#v",

strT.String())

outputT,

errT

:=

xml.MarshalIndent(person1,

"

",

"

")if

errT

!=

nil

{

t.Printfln("XML缩进编码时发生错误:%v",

errT)

return}

os.Stdout.Write(outputT)序列化结果XML字符串为:"<personid=\"postalCode=\"100099\"><name>张三</name><age>25</age><Married>false</Married><mobiles><mobile>lt;/mobile><mobile>lt;/mobile></mobiles><State>中国</State><City>北京</City><Detail>海淀区中关村1号</Detail><secondAddresspostalCode=\"210001\"><State>中国</State><City>上海</City><Detail>徐汇区南京路1号</Detail></secondAddress><!--信息有待完善--></person>"<personid=postalCode="100099"><name>张三</name><age>25</age><Married>false</Married><mobiles><mobile>lt;/mobile><mobile>lt;/mobile></mobiles><State>中国</State><City>北京</City><Detail>海淀区中关村1号</Detail><secondAddresspostalCode="210001"><State>中国</State><City>上海</City><Detail>徐汇区南京路1号</Detail></secondAddress><!--信息有待完善--></person>进行XML序列化(编码)person1

:=

&Person{Name:

"张三",

ID:

,

Age:

25,

Married:

false,

Mobile:

[]string{,

},

height:

170,

AddressType:

AddressType{State:

"中国",

City:

"北京",

Detail:

"海淀区中关村1号",

PostalCode:

"100099",

remark:

"路口右转"},

SecondAddress:

AddressType{State:

"中国",

City:

"上海",

Detail:

"徐汇区南京路1号",

PostalCode:

"210001",

remark:

"无"},

Remark:

"信息有待完善"}

var

strT

strings.BuilderencoderT

:=

xml.NewEncoder(&strT)errT

:=

encoderT.Encode(person1)if

errT

!=

nil

{

t.Printfln("XML编码时发生错误:%v",

errT.Error())

return}t.Printfln("XML字符串为:%#v",

strT.String())

outputT,

errT

:=

xml.MarshalIndent(person1,

"

",

"

")if

errT

!=

nil

{

t.Printfln("XML缩进编码时发生错误:%v",

errT)

return}

os.Stdout.Write(outputT)XML序列化说明1

处理XML格式文本需要使用“encoding/xml”包

Person类型是自定义的用于存储个人信息的数据结构类型

Person结构类型中的大多数字段(成员变量)后都有一个用于指导如何进行XML序列化的特殊字符串,称作“标记”(tag),也称为XML序列化描述字符串,简称描述字符串

例如,“Name”字段后用反引号括起来的描述字符串`xml:"name"`,表示Name字段在序列化后的XML中将被转换成名字为“name”的XML元素节点XML序列化说明2

Person结构中的第一行“XMLNamexml.Name`xml:"person"`”并非定义一个字段,而是结构体中为XML序列化专用的一个设置写法,用于指定该结构在XML序列化后根节点的名称

描述字符串如果是类似`xml:“id,attr”`的形式,则表明该字段将被序列化成为它上级节点的一个名为“id”的属性(例子中是Person结构中的ID字段)

描述字符串如果是类似`xml:"phone,omitempty"`的形式,则表示如果该字段有值则将正常序列化为名字为“phone”的XML元素节点,否则如果是空值(包括各种Go语言中的零值,例如nil)则该节点将被省略XML序列化说明3描述字符串如果是类似`xml:"mobiles>mobile"的形式,则表示该字段将被序列化成名为mobile的元素节点,并且放在mobiles元素节点之内成为它的下一级节点;这种嵌套的级别可以是多级的,例如`xml:"mobiles>mobile>subs“

Person结构中的Mobile字段是[]string类型的,表示一个人可以有多个手机号,结合描述字符串`xml:"mobiles>mobile",这样序列化出来的XML文本中,将用mobiles节点下并列的名为“mobile”的XML元素节点来表示多个手机号;如果描述字符串为`xml:"mobile",则会有多个mobile节点被直接放在根节点(即本例中的person节点)下形如`xml:",comment"`的描述字符串修饰的字段将被序列化成XML中的注释,将不起数据存储的作用XML序列化说明4没有加上描述字符串的字段,类似Person结构中的Married字段,将被序列化为与该字段名字一致的XML节点所有被导出的字段(即大写字母开头的字段)才可以被序列化,小写字母开头的字段将被忽略,例如本例Person结构中的height字段,虽然后面写有XML序列化描述字符串,但仍然在序列化后的XML文本中被忽略掉

Person结构中的SecondAddress字段是AddressType类型的,这也是我们在代码中自定义的一个结构,用于表示个人住址信息;这是结构体中包含复合数据类型以及嵌套另一个结构的方法XML序列化说明5

匿名字段:在Person结构中没有字段名的也是AddressType类型的字段

匿名字段是Go语言中实现类似面向对象中“继承”概念的重要手段

一个结构体中如果有一个匿名字段,而该匿名字段又是一个结构类型,则该匿名字段所代表结构类型的所有字段会被自动导入到该结构体中引用结构体中匿名字段时,直接用该匿名字段的数据类型作为字段名即可XML序列化说明6

AddressType结构类型中的PostalCode字段的XML描述字符串演示了如何在某个子节点而非根节点中添加属性

使用encoding/xml包中的Encoder数据类型来做XML的编码(将数据序列化为XMLxml.MarshalIndent函数可以编码出带有缩进的XML文本,返回的是[]byte类型的数据,需要转换成字符串才能输出XML序列化说明7

AddressType结构类型中的PostalCode字段的XML描述字符串演示了如何在某个子节点而非根节点中添加属性

使用encoding/xml包中的Encoder数据类型来做XML的编码(将数据序列化为XMLxml.MarshalIndent函数可以编码出带有缩进的XML文本,返回的是[]byte类型的数据,需要转换成字符串才能输出XML格式的文本反序列化decoderT

:=

xml.NewDecoder(fileT)errT

=

decoderT.Decode(person1)

if

errT

!=

nil

{}

t.Printfln("person1:%#v",

person1)

person2

:=

&Person{}

bytesT,

errT

:=

ioutil.ReadFile(`c:\test\person1.xml`)if

errT

!=

nil

{}

errT

=

xml.Unmarshal(bytesT,

person2)if

errT

!=

nil

{}

t.Printfln("person2:%#v",

person2)XML处理的补充知识1如果在结构体中没有定义XMLName字段,XML序列化时将以结构名字作为XML文本中根节点的名称普通的数据类型也可以被进行XML编码,此时生成的节点名为该类型的名称描述字符串为`xml:"-"`的结构体中字段将被忽略描述字符串为`xml:",innerxml"`的字段,将原样放在XML中而不会被加上标签(即不会生成XML元素节点),如果需要标签则应自行加上XML处理的补充知识2描述字符串为`xml:",chardata"`的字段,也不会生成XML元素节点,将被作为字符数据直接放入描述字符串为`xml:",cdata"`的字段,同样也不会生成XML元素节点,而是编码为XML中的CDATA字符数据形式,该形式主要用于放入包含一些特殊字符的文本如果要让CDATA字符数据在XML中放于一个元素节点之内,需要定义一个结构类型,例子见下页:CDATA的应用示例1type

CDATA

struct

{

string

`xml:",cdata"`}type

CodeData

struct

{

CodeName

string

CodeType

string

`xml:",attr"`

CodeDescription

string

`xml:",innerxml"`

CodeData1

[]byte

`xml:",chardata"`

CodeData2

CDATA

Remark

string

`xml:"-"`}CDATA的应用示例2func

main()

{

code1

:=

new(CodeData)

code1.CodeName

=

"测试代码"

code1.CodeType

=

"Go"

code1.CodeDescription

=

"\n<CodeDescription>本段描述将被原样保留</CodeDescription>"

code1.CodeData1

=

[]byte{0x65,

0x33,

0x32}

code1.CodeData2

=

CDATA{`for

i

:=

0;

i

<=

18;

i

++

{fmt.Printf("18");}`}

code1.Remark

=

"本段备注将被忽略"

xmlBytesT,

errT

:=

xml.MarshalIndent(code1,

"",

"

")

if

errT

!=

nil

{

t.Printfln("XML编码时发生错误:%v",

errT)

return

}

t.Printfln("%v",

string(xmlBytesT))}CDATA的应用示例3单个浮点数的XML:<float64>64.8</float64>code1编码后的XML:<CodeDataCodeType="Go"><CodeName>测试代码</CodeName><CodeDescription>本段描述将被原样保留</CodeDescription>e32<CodeData2><![CDATA[fori:=0;i<=18;i++{fmt.Printf("18");}]]></CodeData2></CodeData>运行结果自行控制某数据类型的XML序列化反序列化func

(v

AddressType)

MarshalXML(e

*xml.Encoder,

start

xml.StartElement)

error

{

stringAllT

:=

v.State

+

"|"

+

v.City

+

"|"

+

v.Detail

+

"|"

+

v.PostalCode

+

"|"

+

v.remark

e.EncodeElement(stringAllT,

start)

return

nil}

func

(p

*AddressType)

UnmarshalXML(d

*xml.Decoder,

start

xml.StartElement)

error

{

var

stringBufT

string

d.DecodeElement(&stringBufT,

&start)

listT

:=

strings.Split(stringBufT,

"|")

*p

=

AddressType{State:

listT[0],

City:

listT[1],

Detail:

listT[2],

PostalCode:

listT[3],

remark:

listT[4]}

return

nil}定义在AddressType数据类型上目录导航10.3JSON格式的处理ContentsJSON数据格式

JSON格式是数据交换格式中使用最广泛的格式之一,虽然起源于JavaScript语言,但实际应用中已经完全实现了跨语言、跨平台的使用JSON格式最大的特点就是写法简单易懂,处理快速,并具备大多数主要基本数据类型的表达能力

Go语言中处理JSON格式的序列化和反序列化与XML相比要简单很多将数据序列化成JSON格式1//

AddressType

表示个人住址的数据结构type

AddressType

struct

{

State

string

City

string

Detail

string

PostalCode

string

remark

string}

//

Person

表示个人信息的数据结构类型type

Person

struct

{

Name

string

ID

string

Age

int

Married

bool

Phone

string

Mobile

[]string

height

float64

AddressType

SecondAddress

AddressType

Remark

string}数据结构一般无需特别处理将数据序列化成JSON格式2person1

:=

&Person{Name:

"张三",

ID:

,

Age:

25,

Married:

false,

Mobile:

[]string{,

},

height:

170,

AddressType:

AddressType{State:

"中国",

City:

"北京",

Detail:

"海淀区中关村1号",

PostalCode:

"100099",

remark:

"路口右转"},

SecondAddress:

AddressType{State:

"中国",

City:

"上海",

Detail:

"徐汇区南京路1号",

PostalCode:

"210001",

remark:

"无"},

Remark:

"信息有待完善"}

var

strT

strings.BuilderencoderT

:=

json.NewEncoder(&strT)errT

:=

encoderT.Encode(person1)if

errT

!=

nil

{}

t.Printfln("JSON字符串为:%#v",

strT.String())

outputT,

errT

:=

json.MarshalIndent(person1,

"

",

"

")if

errT

!=

nil

{}

os.Stdout.Write(outputT)t.SaveStringToFile(string(outputT),

`c:\test\person1.json`)将数据序列化成JSON格式3JSON字符串为:"{\"Name\":\"张三\",\"ID\":\",\"Age\":25,\"Married\":false,\"Phone\":\"\",\"Mobile\":[\",\"],\"State\":\"中国\",\"City\":\"北京\",\"Detail\":\"海淀区中关村1号\",\"PostalCode\":\"100099\",\"SecondAddress\":{\"State\":\"中国\",\"City\":\"上海\",\"Detail\":\"徐汇区南京路1号\",\"PostalCode\":\"210001\"},\"Remark\":\"信息有待完善\"}\n"

{"Name":"张三","ID":,"Age":25,"Married":false,"Phone":"","Mobile":[,],"State":"中国","City":"北京","Detail":"海淀区中关村1号","PostalCode":"100099","SecondAddress":{"State":"中国","City":"上海","Detail":"徐汇区南京路1号","PostalCode":"210001"},"Remark":"信息有待完善"}将JSON格式的文本反序列化decoderT

:=

json.NewDecoder(fileT)errT

=

decoderT.Decode(person1)if

errT

!=

nil

{}

t.Printfln("person1:%#v",

person1)

person2

:=

&Person{}

bytesT,

errT

:=

ioutil.ReadFile(`c:\test\person1.json`)if

errT

!=

nil

{}

errT

=

json.Unmarshal(bytesT,

person2)if

errT

!=

nil

{}

t.Printfln("person2:%#v",

person2)JSON序列化/反序列化时使用描述字符串type

Person

struct

{

Name

string

`json:"name"`

ID

string

Age

int

`json:",string"`

Married

bool

`json:",omitempty"`

Phone

string

Mobile

[]string

height

float64

`json:"height"`

AddressType

SecondAddress

AddressType

Remark

string

`json:"-"`}与XML类似,JSON也可以加描述字符串特殊说明使用类似`json:"name"`的JSON序列化描述字符串,可以设置该字段在JSON中的键(key)名,这也可以突破不使用描述字符串时键名必须为大写字母开头的限制,这一点在解析网络上很多JSON接口或文件时非常有用,因为除了Go语言之外,很少有其他语言限制这一点

`json:",string"`这样的描述字符串一般用于描述数字类型的字段,表示虽然该字段是数字,但是也按照字符串形式来编码控制自定义数据类型的JSON序列化/反序列化func

(v

AddressType)

MarshalJSON()

([]byte,

error)

{

stringAllT

:=

v.State

+

"|"

+

v.City

+

"|"

+

v.Detail

+

"|"

+

v.PostalCode

+

"|"

+

v.remark

return

json.Marshal(stringAllT)}

func

(p

*AddressType)

UnmarshalJSON(b

[]byte)

error

{

var

stringBufT

string

errT

:=

json.Unmarshal(b,

&stringBufT)

if

errT

!=

nil

{

return

errT

}

listT

:=

strings.Split(stringBufT,

"|")

*p

=

AddressType{State:

listT[0],

City:

listT[1],

Detail:

listT[2],

PostalCode:

listT[3],

remark:

listT[4]}

return

nil}注意思考两个函数为什么一个定义在值上,一个定义在引用上用空接口类型实现复杂结构的JSON序列化map1T

:=

map[string]interface{}{

"Name":

"小明",

"Age":

11,

"Gender":

"男",

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论