《Go語言從入門到精通》Go語言中數(shù)據(jù)格式的分析與轉(zhuǎn)換_第1頁
《Go語言從入門到精通》Go語言中數(shù)據(jù)格式的分析與轉(zhuǎn)換_第2頁
《Go語言從入門到精通》Go語言中數(shù)據(jù)格式的分析與轉(zhuǎn)換_第3頁
《Go語言從入門到精通》Go語言中數(shù)據(jù)格式的分析與轉(zhuǎn)換_第4頁
《Go語言從入門到精通》Go語言中數(shù)據(jù)格式的分析與轉(zhuǎn)換_第5頁
已閱讀5頁,還剩34頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

Go語言中數(shù)據(jù)格式的分析與轉(zhuǎn)換Go語言從入門到精通了解編程中常用的數(shù)據(jù)交換格式掌握Go語言中JSON格式數(shù)據(jù)的分析與處理01FORMAT02XML03JSONtarget目標掌握Go語言中XML格式數(shù)據(jù)的分析與處理目錄導航10.1常見的數(shù)據(jù)交換格式Contents數(shù)據(jù)交換格式在不同的計算機之間、應用程序之間,通過文件、網(wǎng)絡等各種途徑進行信息交換時,為了雙方都能夠理解而制定的數(shù)據(jù)格式。

數(shù)據(jù)交換格式的基本要求是能夠跨平臺、跨語言得到準確無誤的理解常見的數(shù)據(jù)交換格式純文本

CSV

XML

JSON(及各種變體)YAMLProtoBuf目錄導航10.2XML格式的處理ContentsXML格式

XML是可擴展標記語言(EXtensibleMarkupLanguage)的縮寫簡稱,它被設計為專注于數(shù)據(jù)的表達而非其他(例如數(shù)據(jù)的顯示樣式等)方面,因此特別適合也主要被應用于傳輸數(shù)據(jù)和存儲數(shù)據(jù)XML格式XML格式是基于文本格式之上的,因此,XML文件就是純文本文件的一種。XML文件可以直接用文本編輯軟件打開,其中內(nèi)容也都是由人可以識別的字符組成的。XML數(shù)據(jù)在程序中的表現(xiàn)形式就是一個字符串XML對文本進行了更高級別的格式要求,以便能夠用一定的文本格式規(guī)范來表現(xiàn)出各種類型的數(shù)據(jù)類型和數(shù)據(jù)結構,能夠支持復雜的數(shù)據(jù)類型并且能對數(shù)據(jù)的取值范圍等做出更具體的規(guī)定和限制將數(shù)據(jù)序列化成XML格式引用encoding/xml包//

Person

準備進行XML序列化的表示個人信息的數(shù)據(jù)結構類型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"`}

準備數(shù)據(jù)結構用到的嵌套數(shù)據(jù)結構//

AddressType

表示個人住址的數(shù)據(jù)結構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:

"海淀區(qū)中關村1號",

PostalCode:

"100099",

remark:

"路口右轉(zhuǎn)"},

SecondAddress:

AddressType{State:

"中國",

City:

"上海",

Detail:

"徐匯區(qū)南京路1號",

PostalCode:

"210001",

remark:

"無"},

Remark:

"信息有待完善"}

var

strT

strings.BuilderencoderT

:=

xml.NewEncoder(&strT)errT

:=

encoderT.Encode(person1)if

errT

!=

nil

{

t.Printfln("XML編碼時發(fā)生錯誤:%v",

errT.Error())

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

strT.String())

outputT,

errT

:=

xml.MarshalIndent(person1,

"

",

"

")if

errT

!=

nil

{

t.Printfln("XML縮進編碼時發(fā)生錯誤:%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>海淀區(qū)中關村1號</Detail><secondAddresspostalCode=\"210001\"><State>中國</State><City>上海</City><Detail>徐匯區(qū)南京路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>海淀區(qū)中關村1號</Detail><secondAddresspostalCode="210001"><State>中國</State><City>上海</City><Detail>徐匯區(qū)南京路1號</Detail></secondAddress><!--信息有待完善--></person>進行XML序列化(編碼)person1

:=

&Person{Name:

"張三",

ID:

,

Age:

25,

Married:

false,

Mobile:

[]string{,

},

height:

170,

AddressType:

AddressType{State:

"中國",

City:

"北京",

Detail:

"海淀區(qū)中關村1號",

PostalCode:

"100099",

remark:

"路口右轉(zhuǎn)"},

SecondAddress:

AddressType{State:

"中國",

City:

"上海",

Detail:

"徐匯區(qū)南京路1號",

PostalCode:

"210001",

remark:

"無"},

Remark:

"信息有待完善"}

var

strT

strings.BuilderencoderT

:=

xml.NewEncoder(&strT)errT

:=

encoderT.Encode(person1)if

errT

!=

nil

{

t.Printfln("XML編碼時發(fā)生錯誤:%v",

errT.Error())

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

strT.String())

outputT,

errT

:=

xml.MarshalIndent(person1,

"

",

"

")if

errT

!=

nil

{

t.Printfln("XML縮進編碼時發(fā)生錯誤:%v",

errT)

return}

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

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

Person類型是自定義的用于存儲個人信息的數(shù)據(jù)結構類型

Person結構類型中的大多數(shù)字段(成員變量)后都有一個用于指導如何進行XML序列化的特殊字符串,稱作“標記”(tag),也稱為XML序列化描述字符串,簡稱描述字符串

例如,“Name”字段后用反引號括起來的描述字符串`xml:"name"`,表示Name字段在序列化后的XML中將被轉(zhuǎn)換成名字為“name”的XML元素節(jié)點XML序列化說明2

Person結構中的第一行“XMLNamexml.Name`xml:"person"`”并非定義一個字段,而是結構體中為XML序列化專用的一個設置寫法,用于指定該結構在XML序列化后根節(jié)點的名稱

描述字符串如果是類似`xml:“id,attr”`的形式,則表明該字段將被序列化成為它上級節(jié)點的一個名為“id”的屬性(例子中是Person結構中的ID字段)

描述字符串如果是類似`xml:"phone,omitempty"`的形式,則表示如果該字段有值則將正常序列化為名字為“phone”的XML元素節(jié)點,否則如果是空值(包括各種Go語言中的零值,例如nil)則該節(jié)點將被省略XML序列化說明3描述字符串如果是類似`xml:"mobiles>mobile"的形式,則表示該字段將被序列化成名為mobile的元素節(jié)點,并且放在mobiles元素節(jié)點之內(nèi)成為它的下一級節(jié)點;這種嵌套的級別可以是多級的,例如`xml:"mobiles>mobile>subs“

Person結構中的Mobile字段是[]string類型的,表示一個人可以有多個手機號,結合描述字符串`xml:"mobiles>mobile",這樣序列化出來的XML文本中,將用mobiles節(jié)點下并列的名為“mobile”的XML元素節(jié)點來表示多個手機號;如果描述字符串為`xml:"mobile",則會有多個mobile節(jié)點被直接放在根節(jié)點(即本例中的person節(jié)點)下形如`xml:",comment"`的描述字符串修飾的字段將被序列化成XML中的注釋,將不起數(shù)據(jù)存儲的作用XML序列化說明4沒有加上描述字符串的字段,類似Person結構中的Married字段,將被序列化為與該字段名字一致的XML節(jié)點所有被導出的字段(即大寫字母開頭的字段)才可以被序列化,小寫字母開頭的字段將被忽略,例如本例Person結構中的height字段,雖然后面寫有XML序列化描述字符串,但仍然在序列化后的XML文本中被忽略掉

Person結構中的SecondAddress字段是AddressType類型的,這也是我們在代碼中自定義的一個結構,用于表示個人住址信息;這是結構體中包含復合數(shù)據(jù)類型以及嵌套另一個結構的方法XML序列化說明5

匿名字段:在Person結構中沒有字段名的也是AddressType類型的字段

匿名字段是Go語言中實現(xiàn)類似面向?qū)ο笾小袄^承”概念的重要手段

一個結構體中如果有一個匿名字段,而該匿名字段又是一個結構類型,則該匿名字段所代表結構類型的所有字段會被自動導入到該結構體中引用結構體中匿名字段時,直接用該匿名字段的數(shù)據(jù)類型作為字段名即可XML序列化說明6

AddressType結構類型中的PostalCode字段的XML描述字符串演示了如何在某個子節(jié)點而非根節(jié)點中添加屬性

使用encoding/xml包中的Encoder數(shù)據(jù)類型來做XML的編碼(將數(shù)據(jù)序列化為XMLxml.MarshalIndent函數(shù)可以編碼出帶有縮進的XML文本,返回的是[]byte類型的數(shù)據(jù),需要轉(zhuǎn)換成字符串才能輸出XML序列化說明7

AddressType結構類型中的PostalCode字段的XML描述字符串演示了如何在某個子節(jié)點而非根節(jié)點中添加屬性

使用encoding/xml包中的Encoder數(shù)據(jù)類型來做XML的編碼(將數(shù)據(jù)序列化為XMLxml.MarshalIndent函數(shù)可以編碼出帶有縮進的XML文本,返回的是[]byte類型的數(shù)據(jù),需要轉(zhuǎn)換成字符串才能輸出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文本中根節(jié)點的名稱普通的數(shù)據(jù)類型也可以被進行XML編碼,此時生成的節(jié)點名為該類型的名稱描述字符串為`xml:"-"`的結構體中字段將被忽略描述字符串為`xml:",innerxml"`的字段,將原樣放在XML中而不會被加上標簽(即不會生成XML元素節(jié)點),如果需要標簽則應自行加上XML處理的補充知識2描述字符串為`xml:",chardata"`的字段,也不會生成XML元素節(jié)點,將被作為字符數(shù)據(jù)直接放入描述字符串為`xml:",cdata"`的字段,同樣也不會生成XML元素節(jié)點,而是編碼為XML中的CDATA字符數(shù)據(jù)形式,該形式主要用于放入包含一些特殊字符的文本如果要讓CDATA字符數(shù)據(jù)在XML中放于一個元素節(jié)點之內(nèi),需要定義一個結構類型,例子見下頁: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編碼時發(fā)生錯誤:%v",

errT)

return

}

t.Printfln("%v",

string(xmlBytesT))}CDATA的應用示例3單個浮點數(shù)的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>運行結果自行控制某數(shù)據(jù)類型的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數(shù)據(jù)類型上目錄導航10.3JSON格式的處理ContentsJSON數(shù)據(jù)格式

JSON格式是數(shù)據(jù)交換格式中使用最廣泛的格式之一,雖然起源于JavaScript語言,但實際應用中已經(jīng)完全實現(xiàn)了跨語言、跨平臺的使用JSON格式最大的特點就是寫法簡單易懂,處理快速,并具備大多數(shù)主要基本數(shù)據(jù)類型的表達能力

Go語言中處理JSON格式的序列化和反序列化與XML相比要簡單很多將數(shù)據(jù)序列化成JSON格式1//

AddressType

表示個人住址的數(shù)據(jù)結構type

AddressType

struct

{

State

string

City

string

Detail

string

PostalCode

string

remark

string}

//

Person

表示個人信息的數(shù)據(jù)結構類型type

Person

struct

{

Name

string

ID

string

Age

int

Married

bool

Phone

string

Mobile

[]string

height

float64

AddressType

SecondAddress

AddressType

Remark

string}數(shù)據(jù)結構一般無需特別處理將數(shù)據(jù)序列化成JSON格式2person1

:=

&Person{Name:

"張三",

ID:

,

Age:

25,

Married:

false,

Mobile:

[]string{,

},

height:

170,

AddressType:

AddressType{State:

"中國",

City:

"北京",

Detail:

"海淀區(qū)中關村1號",

PostalCode:

"100099",

remark:

"路口右轉(zhuǎn)"},

SecondAddress:

AddressType{State:

"中國",

City:

"上海",

Detail:

"徐匯區(qū)南京路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`)將數(shù)據(jù)序列化成JSON格式3JSON字符串為:"{\"Name\":\"張三\",\"ID\":\",\"Age\":25,\"Married\":false,\"Phone\":\"\",\"Mobile\":[\",\"],\"State\":\"中國\",\"City\":\"北京\",\"Detail\":\"海淀區(qū)中關村1號\",\"PostalCode\":\"100099\",\"SecondAddress\":{\"State\":\"中國\",\"City\":\"上海\",\"Detail\":\"徐匯區(qū)南京路1號\",\"PostalCode\":\"210001\"},\"Remark\":\"信息有待完善\"}\n"

{"Name":"張三","ID":,"Age":25,"Married":false,"Phone":"","Mobile":[,],"State":"中國","City":"北京","Detail":"海淀區(qū)中關村1號","PostalCode":"100099","SecondAddress":{"State":"中國","City":"上海","Detail":"徐匯區(qū)南京路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)名,這也可以突破不使用描述字符串時鍵名必須為大寫字母開頭的限制,這一點在解析網(wǎng)絡上很多JSON接口或文件時非常有用,因為除了Go語言之外,很少有其他語言限制這一點

`json:",string"`這樣的描述字符串一般用于描述數(shù)字類型的字段,表示雖然該字段是數(shù)字,但是也按照字符串形式來編碼控制自定義數(shù)據(jù)類型的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}注意思考兩個函數(shù)為什么一個定義在值上,一個定義在引用上用空接口類型實現(xiàn)復雜結構的JSON序列化map1T

:=

map[string]interface{}{

"Name":

"小明",

"Age":

11,

"Gender":

"男",

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論