- json
- pem
- xml
json
json包實(shí)現(xiàn)了json對(duì)象的編解碼强衡,參見(jiàn)RFC 4627。Json對(duì)象和go類(lèi)型的映射關(guān)系請(qǐng)參見(jiàn)Marshal和Unmarshal函數(shù)的文檔铃慷。
參見(jiàn)"JSON and Go"獲取本包的一個(gè)介紹:http://golang.org/doc/articles/json_and_go.html
type InvalidUTF8Error
type InvalidUTF8Error struct {
S string // 引發(fā)錯(cuò)誤的完整字符串
}
Go 1.2之前版本,當(dāng)試圖編碼一個(gè)包含非法utf-8序列的字符串時(shí)會(huì)返回本錯(cuò)誤。Go 1.2及之后版本宋渔,編碼器會(huì)強(qiáng)行將非法字節(jié)替換為unicode字符U+FFFD來(lái)使字符串合法弹灭。本錯(cuò)誤已不會(huì)再出現(xiàn)督暂,但出于向后兼容考慮而保留。
func (*InvalidUTF8Error) Error
func (e *InvalidUTF8Error) Error() string
type InvalidUnmarshalError
type InvalidUnmarshalError struct {
Type reflect.Type
}
InvalidUnmarshalError用于描述一個(gè)傳遞給解碼器的非法參數(shù)穷吮。(解碼器的參數(shù)必須是非nil指針)
func (*InvalidUnmarshalError) Error
func (e *InvalidUnmarshalError) Error() string
type SyntaxError
type SyntaxError struct {
msg string // description of error
Offset int64 // error occurred after reading Offset bytes
}
SyntaxError表示一個(gè)json語(yǔ)法錯(cuò)誤逻翁。
func (*SyntaxError) Error
func (e *SyntaxError) Error() string
type UnmarshalFieldError
type UnmarshalFieldError struct {
Key string
Type reflect.Type
Field reflect.StructField
}
UnmarshalFieldError表示一個(gè)json對(duì)象的鍵指向一個(gè)非導(dǎo)出字段。(因此不能寫(xiě)入捡鱼;已不再使用八回,出于兼容保留)
func (*UnmarshalFieldError) Error
func (e *UnmarshalFieldError) Error() string
type UnmarshalTypeError
type UnmarshalTypeError struct {
Value string // 描述json值:"bool", "array", "number -5"
Type reflect.Type // 不能轉(zhuǎn)化為的go類(lèi)型
}
UnmarshalTypeError表示一個(gè)json值不能轉(zhuǎn)化為特定的go類(lèi)型的值。
func (*UnmarshalTypeError) Error
func (e *UnmarshalTypeError) Error() string
type UnsupportedTypeError
type UnsupportedTypeError struct {
Type reflect.Type
}
UnsupportedTypeError表示試圖編碼一個(gè)不支持類(lèi)型的值驾诈。
func (*UnsupportedTypeError) Error
func (e *UnsupportedTypeError) Error() string
type UnsupportedValueError
type UnsupportedValueError struct {
Value reflect.Value
Str string
}
func (*UnsupportedValueError) Error
func (e *UnsupportedValueError) Error() string
type MarshalerError
type MarshalerError struct {
Type reflect.Type
Err error
}
func (*MarshalerError) Error
func (e *MarshalerError) Error() string
type Number
type Number string
Number類(lèi)型代表一個(gè)json數(shù)字字面量缠诅。
func (Number) Int64
func (n Number) Int64() (int64, error)
將該數(shù)字作為int64類(lèi)型返回。
func (Number) Float64
func (n Number) Float64() (float64, error)
將該數(shù)字作為float64類(lèi)型返回乍迄。
func (Number) String
func (n Number) String() string
返回該數(shù)字的字面值文本表示管引。
type RawMessage
type RawMessage []byte
RawMessage類(lèi)型是一個(gè)保持原本編碼的json對(duì)象。本類(lèi)型實(shí)現(xiàn)了Marshaler和Unmarshaler接口闯两,用于延遲json的解碼或者預(yù)計(jì)算json的編碼褥伴。
type Color struct {
Space string
Point json.RawMessage // delay parsing until we know the color space
}
type RGB struct {
R uint8
G uint8
B uint8
}
type YCbCr struct {
Y uint8
Cb int8
Cr int8
}
func main() {
var j = []byte(`[
{"Space": "YCbCr", "Point": {"Y": 255, "Cb": 0, "Cr": -10}},
{"Space": "RGB", "Point": {"R": 98, "G": 218, "B": 255}}
]`)
var colors []Color
err := json.Unmarshal(j, &colors)
if err != nil {
log.Fatalln("error:", err)
}
for _, c := range colors {
var dst interface{}
switch c.Space {
case "RGB":
dst = new(RGB)
case "YCbCr":
dst = new(YCbCr)
}
err := json.Unmarshal(c.Point, dst)
if err != nil {
log.Fatalln("error:", err)
}
fmt.Println(c.Space, dst)
}
}
func (*RawMessage) MarshalJSON
func (m *RawMessage) MarshalJSON() ([]byte, error)
MarshalJSON返回*m的json編碼。
func (*RawMessage) UnmarshalJSON
func (m *RawMessage) UnmarshalJSON(data []byte) error
UnmarshalJSON將*m設(shè)為data的一個(gè)拷貝生蚁。
type Marshaler
type Marshaler interface {
MarshalJSON() ([]byte, error)
}
實(shí)現(xiàn)了Marshaler接口的類(lèi)型可以將自身序列化為合法的json描述噩翠。
type Unmarshaler
type Unmarshaler interface {
UnmarshalJSON([]byte) error
}
實(shí)現(xiàn)了Unmarshaler接口的對(duì)象可以將自身的json描述反序列化。該方法可以認(rèn)為輸入是合法的json字符串邦投。如果要在方法返回后保存自身的json數(shù)據(jù)伤锚,必須進(jìn)行拷貝。
func Compact
func Compact(dst *bytes.Buffer, src []byte) error
Compact函數(shù)將json編碼的src中無(wú)用的空白字符剔除后寫(xiě)入dst志衣。
func HTMLEscape
func HTMLEscape(dst *bytes.Buffer, src []byte)
HTMLEscape 函數(shù)將json編碼的src中的<屯援、>、&念脯、U+2028 和U+2029字符替換為\u003c狞洋、\u003e、\u0026绿店、\u2028吉懊、\u2029 轉(zhuǎn)義字符串庐橙,以便json編碼可以安全的嵌入HTML的<script>標(biāo)簽里。因?yàn)闅v史原因借嗽,網(wǎng)絡(luò)瀏覽器不支持在<script>標(biāo)簽中使用標(biāo)準(zhǔn)HTML轉(zhuǎn)義态鳖, 因此必須使用另一種json編碼方案。
func Indent
func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error
Indent函數(shù)將json編碼的調(diào)整縮進(jìn)之后寫(xiě)入dst恶导。每一個(gè)json元素/數(shù)組都另起一行開(kāi)始浆竭,以prefix為起始,一或多個(gè)indent縮進(jìn)(數(shù)目看嵌套層數(shù))惨寿。寫(xiě)入dst的數(shù)據(jù)起始沒(méi)有prefix字符邦泄,也沒(méi)有indent字符,最后也不換行裂垦,因此可以更好的嵌入其他格式化后的json數(shù)據(jù)里顺囊。
type Road struct {
Name string
Number int
}
func main() {
roads := []Road{
{"Diamond Fork", 29},
{"Sheep Creek", 51},
}
b, err := json.Marshal(roads)
if err != nil {
log.Fatal(err)
}
var out bytes.Buffer
json.Indent(&out, b, "=", "\t")
out.WriteTo(os.Stdout)
}
func Marshal
func Marshal(v interface{}) ([]byte, error)
Marshal函數(shù)返回v的json編碼。
Marshal函數(shù)會(huì)遞歸的處理值缸废。如果一個(gè)值實(shí)現(xiàn)了Marshaler接口切非nil指針包蓝,會(huì)調(diào)用其MarshalJSON方法來(lái)生成json編碼。nil指針異常并不是嚴(yán)格必需的企量,但會(huì)模擬與UnmarshalJSON的行為類(lèi)似的必需的異常测萎。
否則,Marshal函數(shù)使用下面的基于類(lèi)型的默認(rèn)編碼格式:
布爾類(lèi)型編碼為json布爾類(lèi)型届巩。
浮點(diǎn)數(shù)硅瞧、整數(shù)和Number類(lèi)型的值編碼為json數(shù)字類(lèi)型。
字符串編碼為json字符串恕汇。角括號(hào)"<"和">"會(huì)轉(zhuǎn)義為"\u003c"和"\u003e"以避免某些瀏覽器吧json輸出錯(cuò)誤理解為HTML腕唧。基于同樣的原因瘾英,"&"轉(zhuǎn)義為"\u0026"枣接。
數(shù)組和切片類(lèi)型的值編碼為json數(shù)組,但[]byte編碼為base64編碼字符串缺谴,nil切片編碼為null但惶。
結(jié)構(gòu)體的值編碼為json對(duì)象。每一個(gè)導(dǎo)出字段變成該對(duì)象的一個(gè)成員湿蛔,除非:
- 字段的標(biāo)簽是"-"
- 字段是空值膀曾,而其標(biāo)簽指定了omitempty選項(xiàng)
空值是false、0阳啥、""添谊、nil指針、nil接口察迟、長(zhǎng)度為0的數(shù)組斩狱、切片耳高、映射。對(duì)象默認(rèn)鍵字符串是結(jié)構(gòu)體的字段名喊废,但可以在結(jié)構(gòu)體字段的標(biāo)簽里指定祝高。結(jié)構(gòu)體標(biāo)簽值里的"json"鍵為鍵名栗弟,后跟可選的逗號(hào)和選項(xiàng)污筷,舉例如下:
// 字段被本包忽略
Field int `json:"-"`
// 字段在json里的鍵為"myName"
Field int `json:"myName"`
// 字段在json里的鍵為"myName"且如果字段為空值將在對(duì)象中省略掉
Field int `json:"myName,omitempty"`
// 字段在json里的鍵為"Field"(默認(rèn)值),但如果字段為空值會(huì)跳過(guò)乍赫;注意前導(dǎo)的逗號(hào)
Field int `json:",omitempty"`
"string"選項(xiàng)標(biāo)記一個(gè)字段在編碼json時(shí)應(yīng)編碼為字符串瓣蛀。它只適用于字符串、浮點(diǎn)數(shù)雷厂、整數(shù)類(lèi)型的字段惋增。這個(gè)額外水平的編碼選項(xiàng)有時(shí)候會(huì)用于和javascript程序交互:
Int64String int64 `json:",string"`
如果鍵名是只含有unicode字符、數(shù)字改鲫、美元符號(hào)诈皿、百分號(hào)、連字符像棘、下劃線和斜杠的非空字符串稽亏,將使用它代替字段名。
匿名的結(jié)構(gòu)體字段一般序列化為他們內(nèi)部的導(dǎo)出字段就好像位于外層結(jié)構(gòu)體中一樣缕题。如果一個(gè)匿名結(jié)構(gòu)體字段的標(biāo)簽給其提供了鍵名截歉,則會(huì)使用鍵名代替字段名,而不視為匿名烟零。
Go結(jié)構(gòu)體字段的可視性規(guī)則用于供json決定那個(gè)字段應(yīng)該序列化或反序列化時(shí)是經(jīng)過(guò)修正了的瘪松。如果同一層次有多個(gè)(匿名)字段且該層次是最小嵌套的(嵌套層次則使用默認(rèn)go規(guī)則),會(huì)應(yīng)用如下額外規(guī)則:
1)json標(biāo)簽為"-"的匿名字段強(qiáng)行忽略锨阿,不作考慮宵睦;
2)json標(biāo)簽提供了鍵名的匿名字段,視為非匿名字段墅诡;
3)其余字段中如果只有一個(gè)匿名字段壳嚎,則使用該字段;
4)其余字段中如果有多個(gè)匿名字段书斜,但壓平后不會(huì)出現(xiàn)沖突诬辈,所有匿名字段壓平;
5)其余字段中如果有多個(gè)匿名字段荐吉,但壓平后出現(xiàn)沖突焙糟,全部忽略,不產(chǎn)生錯(cuò)誤样屠。
對(duì)匿名結(jié)構(gòu)體字段的管理是從go1.1開(kāi)始的穿撮,在之前的版本缺脉,匿名字段會(huì)直接忽略掉。
映射類(lèi)型的值編碼為json對(duì)象悦穿。映射的鍵必須是字符串攻礼,對(duì)象的鍵直接使用映射的鍵。
指針類(lèi)型的值編碼為其指向的值(的json編碼)栗柒。nil指針編碼為null礁扮。
接口類(lèi)型的值編碼為接口內(nèi)保持的具體類(lèi)型的值(的json編碼)。nil接口編碼為null瞬沦。
通道太伊、復(fù)數(shù)、函數(shù)類(lèi)型的值不能編碼進(jìn)json逛钻。嘗試編碼它們會(huì)導(dǎo)致Marshal函數(shù)返回UnsupportedTypeError僚焦。
Json不能表示循環(huán)的數(shù)據(jù)結(jié)構(gòu),將一個(gè)循環(huán)的結(jié)構(gòu)提供給Marshal函數(shù)會(huì)導(dǎo)致無(wú)休止的循環(huán)曙痘。
type ColorGroup struct {
ID int
Name string
Colors []string
}
func main() {
group := ColorGroup{
ID: 1,
Name: "Reds",
Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
}
b, err := json.Marshal(group)
if err != nil {
fmt.Println("error:", err)
}
os.Stdout.Write(b)
}
func MarshalIndent
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
MarshalIndent類(lèi)似Marshal但會(huì)使用縮進(jìn)將輸出格式化芳悲。
func Unmarshal
func Unmarshal(data []byte, v interface{}) error
Unmarshal函數(shù)解析json編碼的數(shù)據(jù)并將結(jié)果存入v指向的值。
Unmarshal和Marshal做相反的操作边坤,必要時(shí)申請(qǐng)映射名扛、切片或指針,有如下的附加規(guī)則:
要將json數(shù)據(jù)解碼寫(xiě)入一個(gè)指針惩嘉,Unmarshal函數(shù)首先處理json數(shù)據(jù)是json字面值null的情況罢洲。此時(shí),函數(shù)將指針設(shè)為nil文黎;否則惹苗,函數(shù)將json數(shù)據(jù)解碼寫(xiě)入指針指向的值;如果指針本身是nil耸峭,函數(shù)會(huì)先申請(qǐng)一個(gè)值并使指針指向它桩蓉。
要將json數(shù)據(jù)解碼寫(xiě)入一個(gè)結(jié)構(gòu)體,函數(shù)會(huì)匹配輸入對(duì)象的鍵和Marshal使用的鍵(結(jié)構(gòu)體字段名或者它的標(biāo)簽指定的鍵名)劳闹,優(yōu)先選擇精確的匹配院究,但也接受大小寫(xiě)不敏感的匹配。
要將json數(shù)據(jù)解碼寫(xiě)入一個(gè)接口類(lèi)型值本涕,函數(shù)會(huì)將數(shù)據(jù)解碼為如下類(lèi)型寫(xiě)入接口:
Bool 對(duì)應(yīng)JSON布爾類(lèi)型
float64 對(duì)應(yīng)JSON數(shù)字類(lèi)型
string 對(duì)應(yīng)JSON字符串類(lèi)型
[]interface{} 對(duì)應(yīng)JSON數(shù)組
map[string]interface{} 對(duì)應(yīng)JSON對(duì)象
nil 對(duì)應(yīng)JSON的null
如果一個(gè)JSON值不匹配給出的目標(biāo)類(lèi)型业汰,或者如果一個(gè)json數(shù)字寫(xiě)入目標(biāo)類(lèi)型時(shí)溢出,Unmarshal函數(shù)會(huì)跳過(guò)該字段并盡量完成其余的解碼操作菩颖。如果沒(méi)有出現(xiàn)更加嚴(yán)重的錯(cuò)誤样漆,本函數(shù)會(huì)返回一個(gè)描述第一個(gè)此類(lèi)錯(cuò)誤的詳細(xì)信息的UnmarshalTypeError。
JSON的null值解碼為go的接口晦闰、指針放祟、切片時(shí)會(huì)將它們?cè)O(shè)為nil鳍怨,因?yàn)閚ull在json里一般表示“不存在”。 解碼json的null值到其他go類(lèi)型時(shí)跪妥,不會(huì)造成任何改變鞋喇,也不會(huì)產(chǎn)生錯(cuò)誤。
當(dāng)解碼字符串時(shí)眉撵,不合法的utf-8或utf-16代理(字符)對(duì)不視為錯(cuò)誤侦香,而是將非法字符替換為unicode字符U+FFFD。
func main() {
var jsonBlob = []byte(`[
{"Name": "Platypus", "Order": "Monotremata"},
{"Name": "Quoll", "Order": "Dasyuromorphia"}
]`)
type Animal struct {
Name string
Order string
}
var animals []Animal
err := json.Unmarshal(jsonBlob, &animals)
if err != nil {
fmt.Println("error:", err)
}
fmt.Printf("%+v", animals)
}
type Decoder
type Decoder struct {
r io.Reader
buf []byte
d decodeState
scanp int // start of unread data in buf
scanned int64 // amount of data already scanned
scan scanner
err error
tokenState int
tokenStack []int
}
Decoder從輸入流解碼json對(duì)象
func main() {
const jsonStream = `
{"Name": "Ed", "Text": "Knock knock."}
{"Name": "Sam", "Text": "Who's there?"}
{"Name": "Ed", "Text": "Go fmt."}
{"Name": "Sam", "Text": "Go fmt who?"}
{"Name": "Ed", "Text": "Go fmt yourself!"}
`
type Message struct {
Name, Text string
}
dec := json.NewDecoder(strings.NewReader(jsonStream))
for {
var m Message
if err := dec.Decode(&m); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
fmt.Printf("%s: %s\n", m.Name, m.Text)
}
}
func NewDecoder
func NewDecoder(r io.Reader) *Decoder
NewDecoder創(chuàng)建一個(gè)從r讀取并解碼json對(duì)象的*Decoder执桌,解碼器有自己的緩沖鄙皇,并可能超前讀取部分json數(shù)據(jù)。
func (*Decoder) Buffered
func (dec *Decoder) Buffered() io.Reader
Buffered方法返回保存在dec緩存里數(shù)據(jù)的讀取器仰挣,該返回值在下次調(diào)用Decode方法之前有效。
func (*Decoder) UseNumber
func (dec *Decoder) UseNumber()
UseNumber方法將dec設(shè)置為當(dāng)接收端是interface{}接口時(shí)將json數(shù)字解碼為Number類(lèi)型而不是float64類(lèi)型
func (*Decoder) Decode
func (dec *Decoder) Decode(v interface{}) error
Decode從輸入流讀取下一個(gè)json編碼值并保存在v指向的值里缠沈,參見(jiàn)Unmarshal函數(shù)的文檔獲取細(xì)節(jié)信息膘壶。
type Encoder
type Encoder struct {
w io.Writer
err error
escapeHTML bool
indentBuf *bytes.Buffer
indentPrefix string
indentValue string
}
Encoder將json對(duì)象寫(xiě)入輸出流。
func NewEncoder
func NewEncoder(w io.Writer) *Encoder
NewEncoder創(chuàng)建一個(gè)將數(shù)據(jù)寫(xiě)入w的*Encoder洲愤。
func (*Encoder) Encode
func (enc *Encoder) Encode(v interface{}) error
Encode將v的json編碼寫(xiě)入輸出流颓芭,并會(huì)寫(xiě)入一個(gè)換行符,參見(jiàn)Marshal函數(shù)的文檔獲取細(xì)節(jié)信息柬赐。
pem
pem包實(shí)現(xiàn)了PEM數(shù)據(jù)編碼(源自保密增強(qiáng)郵件協(xié)議)亡问。目前PEM編碼主要用于TLS密鑰和證書(shū)。參見(jiàn)RFC 1421
type Block
type Block struct {
Type string // 得自前言的類(lèi)型(如"RSA PRIVATE KEY")
Headers map[string]string // 可選的頭項(xiàng)
Bytes []byte // 內(nèi)容解碼后的數(shù)據(jù)肛宋,一般是DER編碼的ASN.1結(jié)構(gòu)
}
Block代表PEM編碼的結(jié)構(gòu)州藕。編碼格式如下:
-----BEGIN Type-----
Headers
base64-encoded Bytes
-----END Type-----
其中Headers是可為空的多行鍵值對(duì)。
func Decode
func Decode(data []byte) (p *Block, rest []byte)
Decode函數(shù)會(huì)從輸入里查找到下一個(gè)PEM格式的塊(證書(shū)酝陈、私鑰等)床玻。它返回解碼得到的Block和剩余未解碼的數(shù)據(jù)。如果未發(fā)現(xiàn)PEM數(shù)據(jù)沉帮,返回(nil, data)锈死。
func Encode
func Encode(out io.Writer, b *Block) error
func EncodeToMemory
func EncodeToMemory(b *Block) []byte
xml
xml包實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的XML 1.0解析器,該解析器可以理解XML名稱空間穆壕。
Constants
const (
// 適用于本包Marshal輸出的一般性XML header
// 本常數(shù)并不會(huì)自動(dòng)添加到本包的輸出里待牵,這里提供主要是出于便利的目的
Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
)
Variables
var HTMLAutoClose = htmlAutoClose
HTMLAutoClose是應(yīng)當(dāng)考慮到自動(dòng)關(guān)閉的HTML元素的集合。
var HTMLEntity = htmlEntity
HTMLEntity是標(biāo)準(zhǔn)HTML entity字符到其翻譯的映射喇勋。
type SyntaxError
type SyntaxError struct {
Msg string
Line int
}
SyntaxError代表XML輸入流的格式錯(cuò)誤缨该。
func (*SyntaxError) Error
func (e *SyntaxError) Error() string
type TagPathError
type TagPathError struct {
Struct reflect.Type
Field1, Tag1 string
Field2, Tag2 string
}
反序列化時(shí),如果字段標(biāo)簽的路徑有沖突茄蚯,就會(huì)返回TagPathError压彭。
func (*TagPathError) Error
func (e *TagPathError) Error() string
type UnsupportedTypeError
type UnsupportedTypeError struct {
Type reflect.Type
}
當(dāng)序列化時(shí)睦优,如果遇到不能轉(zhuǎn)化為XML的類(lèi)型,就會(huì)返回UnsupportedTypeError壮不。
func (*UnsupportedTypeError) Error
func (e *UnsupportedTypeError) Error() string
type UnmarshalError
type UnmarshalError string
UnmarshalError代表反序列化時(shí)出現(xiàn)的錯(cuò)誤汗盘。
func (UnmarshalError) Error
func (e UnmarshalError) Error() string
type CharData
type CharData []byte
CharData類(lèi)型代表XML字符數(shù)據(jù)(原始文本),其中XML轉(zhuǎn)義序列已經(jīng)被它們所代表的字符取代询一。
func (CharData) Copy
func (c CharData) Copy() CharData
type Comment
type Comment []byte
Comment代表XML注釋?zhuān)袷綖橐酰衅胁话⑨寴?biāo)記<!—和-->。
func (Comment) Copy
func (c Comment) Copy() Comment
type Directive
type Directive []byte
Directive代表XML指示健蕊,格式為<!directive>菱阵,切片中不包含標(biāo)記<!和>。
func (Directive) Copy
func (d Directive) Copy() Directive
type ProcInst
type ProcInst struct {
Target string
Inst []byte
}
ProcInst代表XML處理指令缩功,格式為<?target inst?>晴及。
func (ProcInst) Copy
func (p ProcInst) Copy() ProcInst
type Name
type Name struct {
Space, Local string
}
Name代表一個(gè)XML名稱(Local字段),并指定名字空間(Space)嫡锌。Decoder.Token方法返回的Token中虑稼,Space標(biāo)識(shí)符是典型的URL而不是被解析的文檔里的短前綴。
type Attr
type Attr struct {
Name Name
Value string
}
Attr代表一個(gè)XML元素的一條屬性(Name=Value)
type StartElement
type StartElement struct {
Name Name
Attr []Attr
}
StartElement代表一個(gè)XML起始元素势木。
func (StartElement) Copy
func (e StartElement) Copy() StartElement
func (StartElement) End
func (e StartElement) End() EndElement
返回e對(duì)應(yīng)的XML結(jié)束元素蛛倦。
type EndElement
type EndElement struct {
Name Name
}
EndElement代表一個(gè)XML結(jié)束元素。
type Token
type Token interface{}
Token接口用于保存token類(lèi)型(CharData啦桌、Comment溯壶、Directive、ProcInst甫男、StartElement且改、EndElement)的值。
func CopyToken
func CopyToken(t Token) Token
CopyToken返回一個(gè)Token的拷貝查剖。
type Marshaler
type Marshaler interface {
MarshalXML(e *Encoder, start StartElement) error
}
實(shí)現(xiàn)了Marshaler接口的類(lèi)型可以將自身序列化為合法的XML元素钾虐。
MarshalXML方法將自身調(diào)用者編碼為零或多個(gè)XML元素。 按照慣例笋庄,數(shù)組或切片會(huì)編碼為一系列元素效扫,每個(gè)成員一條。使用start作為元素標(biāo)簽并不是必須的直砂,但這么做可以幫助Unmarshal方法正確的匹配XML元素和結(jié)構(gòu)體字段菌仁。一個(gè)常用的策略是在同一個(gè)層次里將每個(gè)獨(dú)立的值對(duì)應(yīng)到期望的XML然后使用e.EncodeElement進(jìn)行編碼。另一個(gè)常用的策略是重復(fù)調(diào)用e.EncodeToken來(lái)一次一個(gè)token的生成XML輸出静暂。編碼后的token必須組成零或多個(gè)XML元素济丘。
type Unmarshaler
type Unmarshaler interface {
UnmarshalXML(d *Decoder, start StartElement) error
}
實(shí)現(xiàn)了Unmarshaler接口的類(lèi)型可以根據(jù)自身的XML元素描述反序列化自身。
UnmarshalXML方法解碼以start起始單個(gè)XML元素。如果它返回了錯(cuò)誤摹迷,外層Unmarshal的調(diào)用將停止執(zhí)行并返回該錯(cuò)誤疟赊。UnmarshalXML方法必須正好“消費(fèi)”一個(gè)XML元素。一個(gè)常用的策略是使用d.DecodeElement 將XML分別解碼到各獨(dú)立值峡碉,然后再將這些值寫(xiě)入U(xiǎn)nmarshalXML的調(diào)用者近哟。另一個(gè)常用的策略是使用d.Token一次一個(gè)token的處理XML對(duì)象。UnmarshalXML通常不使用d.RawToken鲫寄。
type MarshalerAttr
type MarshalerAttr interface {
MarshalXMLAttr(name Name) (Attr, error)
}
實(shí)現(xiàn)了MarshalerAttr接口的類(lèi)型可以將自身序列化為合法的XML屬性吉执。
MarshalXMLAttr返回一個(gè)值為方法調(diào)用者編碼后的值的XML屬性。使用name作為屬性的name并非必須的地来,但這么做可以幫助Unmarshal方法正確的匹配屬性和結(jié)構(gòu)體字段戳玫。如果MarshalXMLAttr返回一個(gè)零值屬性Attr{},將不會(huì)生成屬性輸出未斑。MarshalXMLAttr只用于有標(biāo)簽且標(biāo)簽有"attr"選項(xiàng)的結(jié)構(gòu)體字段咕宿。
type UnmarshalerAttr
type UnmarshalerAttr interface {
UnmarshalXMLAttr(attr Attr) error
}
實(shí)現(xiàn)了UnmarshalerAttr接口的類(lèi)型可以根據(jù)自身的XML屬性形式的描述反序列化自身。
UnmarshalXMLAttr解碼單個(gè)的XML屬性颂碧。如果它返回一個(gè)錯(cuò)誤荠列,外層的Umarshal調(diào)用會(huì)停止執(zhí)行并返回該錯(cuò)誤。UnmarshalXMLAttr只有在結(jié)構(gòu)體字段的標(biāo)簽有"attr"選項(xiàng)時(shí)才被使用载城。
func Escape
func Escape(w io.Writer, s []byte)
Escape類(lèi)似EscapeText函數(shù)但會(huì)忽略返回的錯(cuò)誤。本函數(shù)是用于保證和Go 1.0的向后兼容费就。應(yīng)用于Go 1.1及以后版本的代碼請(qǐng)使用EscapeText诉瓦。
func EscapeText
func EscapeText(w io.Writer, s []byte) error
EscapeText向w中寫(xiě)入經(jīng)過(guò)適當(dāng)轉(zhuǎn)義的、有明文s具有相同意義的XML文本力细。
func Marshal
func Marshal(v interface{}) ([]byte, error)
Marshal函數(shù)返回v的XML編碼睬澡。
Marshal處理數(shù)組或者切片時(shí)會(huì)序列化每一個(gè)元素。Marshal處理指針時(shí)眠蚂,會(huì)序列化其指向的值煞聪;如果指針為nil,則啥也不輸出逝慧。Marshal處理接口時(shí)昔脯,會(huì)序列化其內(nèi)包含的具體類(lèi)型值,如果接口值為nil笛臣,也是不輸出云稚。Marshal處理其余類(lèi)型數(shù)據(jù)時(shí),會(huì)輸出一或多個(gè)包含數(shù)據(jù)的XML元素沈堡。
XML元素的名字按如下優(yōu)先順序獲染渤隆:
- 如果數(shù)據(jù)是結(jié)構(gòu)體,其XMLName字段的標(biāo)簽
- 類(lèi)型為xml.Name的XMLName字段的值
- 數(shù)據(jù)是某結(jié)構(gòu)體的字段,其標(biāo)簽
- 數(shù)據(jù)是某結(jié)構(gòu)體的字段鲸拥,其字段名
- 被序列化的類(lèi)型的名字
一個(gè)結(jié)構(gòu)體的XML元素包含該結(jié)構(gòu)體所有導(dǎo)出字段序列化后的元素拐格,有如下例外:
- XMLName字段,如上所述刑赶,會(huì)省略
- 具有標(biāo)簽"-"的字段會(huì)省略
- 具有標(biāo)簽"name,attr"的字段會(huì)成為該XML元素的名為name的屬性
- 具有標(biāo)簽",attr"的字段會(huì)成為該XML元素的名為字段名的屬性
- 具有標(biāo)簽",chardata"的字段會(huì)作為字符數(shù)據(jù)寫(xiě)入捏浊,而非XML元素
- 具有標(biāo)簽",innerxml"的字段會(huì)原樣寫(xiě)入,而不會(huì)經(jīng)過(guò)正常的序列化過(guò)程
- 具有標(biāo)簽",comment"的字段作為XML注釋寫(xiě)入角撞,而不經(jīng)過(guò)正常的序列化過(guò)程呛伴,該字段內(nèi)不能有"--"字符串
- 標(biāo)簽中包含"omitempty"選項(xiàng)的字段如果為空值會(huì)省略
空值為false、0谒所、nil指針热康、nil接口、長(zhǎng)度為0的數(shù)組劣领、切片姐军、映射
- 匿名字段(其標(biāo)簽無(wú)效)會(huì)被處理為其字段是外層結(jié)構(gòu)體的字段
如果一個(gè)字段的標(biāo)簽為"a>b>c",則元素c將會(huì)嵌套進(jìn)其上層元素a和b中尖淘。如果該字段相鄰的字段標(biāo)簽指定了同樣的上層元素奕锌,則會(huì)放在同一個(gè)XML元素里。
參見(jiàn)MarshalIndent的例子村生。如果要求Marshal序列化通道惊暴、函數(shù)或者映射會(huì)返回錯(cuò)誤。
func MarshalIndent
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)
MarshalIndent功能類(lèi)似Marshal趁桃。但每個(gè)XML元素會(huì)另起一行并縮進(jìn)辽话,該行以prefix起始,后跟一或多個(gè)indent的拷貝(根據(jù)嵌套層數(shù))卫病。
type Address struct {
City, State string
}
type Person struct {
XMLName xml.Name `xml:"person"`
Id int `xml:"id,attr"`
FirstName string `xml:"name>first"`
LastName string `xml:"name>last"`
Age int `xml:"age"`
Height float32 `xml:"height,omitempty"`
Married bool
Address
Comment string `xml:",comment"`
}
func main() {
v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42}
v.Comment = " Need more details. "
v.Address = Address{"Hanga Roa", "Easter Island"}
output, err := xml.MarshalIndent(v, " ", " ")
if err != nil {
fmt.Printf("error: %v\n", err)
}
os.Stdout.Write(output)
}
func Unmarshal
func Unmarshal(data []byte, v interface{}) error
Unmarshal解析XML編碼的數(shù)據(jù)并將結(jié)果存入v指向的值油啤。v只能指向結(jié)構(gòu)體、切片或者和字符串蟀苛。良好格式化的數(shù)據(jù)如果不能存入v益咬,會(huì)被丟棄。
因?yàn)閁nmarshal使用reflect包帜平,它只能填寫(xiě)導(dǎo)出字段幽告。本函數(shù)好似用大小寫(xiě)敏感的比較來(lái)匹配XML元素名和結(jié)構(gòu)體的字段名/標(biāo)簽鍵名。
Unmarshal函數(shù)使用如下規(guī)則將XML元素映射到結(jié)構(gòu)體字段上罕模。這些規(guī)則中评腺,字段標(biāo)簽指的是結(jié)構(gòu)體字段的標(biāo)簽鍵'xml'對(duì)應(yīng)的值(參見(jiàn)上面的例子):
* 如果結(jié)構(gòu)體字段的類(lèi)型為字符串或者[]byte,且標(biāo)簽為",innerxml"淑掌,
Unmarshal函數(shù)直接將對(duì)應(yīng)原始XML文本寫(xiě)入該字段蒿讥,其余規(guī)則仍適用。
* 如果結(jié)構(gòu)體字段類(lèi)型為xml.Name且名為XMLName,Unmarshal會(huì)將元素名寫(xiě)入該字段
* 如果字段XMLName的標(biāo)簽的格式為"name"或"namespace-URL name"芋绸,
XML元素必須有給定的名字(以及可選的名字空間)媒殉,否則Unmarshal會(huì)返回錯(cuò)誤。
* 如果XML元素的屬性的名字匹配某個(gè)標(biāo)簽",attr"為字段的字段名摔敛,或者匹配某個(gè)標(biāo)簽為"name,attr"
的字段的標(biāo)簽名廷蓉,Unmarshal會(huì)將該屬性的值寫(xiě)入該字段。
* 如果XML元素包含字符數(shù)據(jù)马昙,該數(shù)據(jù)會(huì)存入結(jié)構(gòu)體中第一個(gè)具有標(biāo)簽",chardata"的字段中桃犬,
該字段可以是字符串類(lèi)型或者[]byte類(lèi)型。如果沒(méi)有這樣的字段行楞,字符數(shù)據(jù)會(huì)丟棄攒暇。
* 如果XML元素包含注釋?zhuān)摂?shù)據(jù)會(huì)存入結(jié)構(gòu)體中第一個(gè)具有標(biāo)簽",comment"的字段中,
該字段可以是字符串類(lèi)型或者[]byte類(lèi)型子房。如果沒(méi)有這樣的字段形用,字符數(shù)據(jù)會(huì)丟棄。
* 如果XML元素包含一個(gè)子元素证杭,其名稱匹配格式為"a"或"a>b>c"的標(biāo)簽的前綴田度,反序列化會(huì)深入
XML結(jié)構(gòu)中尋找具有指定名稱的元素,并將最后端的元素映射到該標(biāo)簽所在的結(jié)構(gòu)體字段解愤。
以">"開(kāi)始的標(biāo)簽等價(jià)于以字段名開(kāi)始并緊跟著">" 的標(biāo)簽镇饺。
* 如果XML元素包含一個(gè)子元素,其名稱匹配某個(gè)結(jié)構(gòu)體類(lèi)型字段的XMLName字段的標(biāo)簽名送讲,
且該結(jié)構(gòu)體字段本身沒(méi)有顯式指定標(biāo)簽名兰怠,Unmarshal會(huì)將該元素映射到該字段。
* 如果XML元素的包含一個(gè)子元素李茫,其名稱匹配夠格結(jié)構(gòu)體字段的字段名,且該字段沒(méi)有任何模式選項(xiàng)
(",attr"肥橙、",chardata"等)魄宏,Unmarshal會(huì)將該元素映射到該字段。
* 如果XML元素包含的某個(gè)子元素不匹配以上任一條存筏,而存在某個(gè)字段其標(biāo)簽為",any"宠互,
Unmarshal會(huì)將該元素映射到該字段。
* 匿名字段被處理為其字段好像位于外層結(jié)構(gòu)體中一樣椭坚。
* 標(biāo)簽為"-"的結(jié)構(gòu)體字段永不會(huì)被反序列化填寫(xiě)予跌。
Unmarshal函數(shù)將XML元素寫(xiě)入string或[]byte時(shí),會(huì)將該元素的字符數(shù)據(jù)串聯(lián)起來(lái)作為值善茎,目標(biāo)[]byte不能是nil券册。
Unmarshal函數(shù)將屬性寫(xiě)入string或[]byte時(shí),會(huì)將屬性的值以字符串/切片形式寫(xiě)入。
Unmarshal函數(shù)將XML元素寫(xiě)入切片時(shí)烁焙,會(huì)將切片擴(kuò)展并將XML元素的子元素映射入新建的值里航邢。
Unmarshal函數(shù)將XML元素/屬性寫(xiě)入bool值時(shí),會(huì)將對(duì)應(yīng)的字符串轉(zhuǎn)化為布爾值骄蝇。
Unmarshal函數(shù)將XML元素/屬性寫(xiě)入整數(shù)或浮點(diǎn)數(shù)類(lèi)型時(shí)膳殷,會(huì)將對(duì)應(yīng)的字符串解釋為十進(jìn)制數(shù)字。不會(huì)檢查溢出九火。
Unmarshal函數(shù)將XML元素寫(xiě)入xml.Name類(lèi)型時(shí)赚窃,會(huì)記錄元素的名稱。
Unmarshal函數(shù)將XML元素寫(xiě)入指針時(shí)岔激,會(huì)申請(qǐng)一個(gè)新值并將XML元素映射入該值勒极。
type Email struct {
Where string `xml:"where,attr"`
Addr string
}
type Address struct {
City, State string
}
type Result struct {
XMLName xml.Name `xml:"Person"`
Name string `xml:"FullName"`
Phone string
Email []Email
Groups []string `xml:"Group>Value"`
Address
}
func main() {
v := Result{Name: "none", Phone: "none"}
data := `
<Person>
<FullName>Grace R. Emlin</FullName>
<Company>Example Inc.</Company>
<Email where="home">
<Addr>gre@example.com</Addr>
</Email>
<Email where='work'>
<Addr>gre@work.com</Addr>
</Email>
<Group>
<Value>Friends</Value>
<Value>Squash</Value>
</Group>
<City>Hanga Roa</City>
<State>Easter Island</State>
</Person>
`
err := xml.Unmarshal([]byte(data), &v)
if err != nil {
fmt.Printf("error: %v", err)
return
}
fmt.Printf("XMLName: %#v\n", v.XMLName)
fmt.Printf("Name: %q\n", v.Name)
fmt.Printf("Phone: %q\n", v.Phone)
fmt.Printf("Email: %v\n", v.Email)
fmt.Printf("Groups: %v\n", v.Groups)
fmt.Printf("Address: %v\n", v.Address)
}
type Decoder
type Decoder struct {
// Strict默認(rèn)設(shè)為true,強(qiáng)制要求符合XML規(guī)范
// 如果設(shè)為false鹦倚,則解析器允許輸入中包含常見(jiàn)的錯(cuò)誤:
// * 如果元素缺少結(jié)束標(biāo)簽河质,解析器會(huì)虛構(gòu)一個(gè)結(jié)束標(biāo)簽以保證返回值來(lái)自良好平衡的Token
// * 屬性值和字符數(shù)據(jù)中,未知或畸形的字符entity(以&開(kāi)始的序列)會(huì)丟在一邊
//
// 設(shè)置:
//
// d.Strict = false
// d.AutoClose = HTMLAutoClose
// d.Entity = HTMLEntity
//
// 可以創(chuàng)建一個(gè)能處理標(biāo)準(zhǔn)HTML的解析器震叙。
//
// Strict模式不會(huì)強(qiáng)制要求XML名稱空間TR掀鹅,特別注意它不會(huì)拒絕使用未定義前綴的名字空間標(biāo)簽
// 這些標(biāo)簽會(huì)將未知前綴作為名字空間URL來(lái)記錄
Strict bool
// 當(dāng)Strict == false時(shí),AutoClose指定一個(gè)元素的集合:
// 這些元素在開(kāi)啟后就立刻結(jié)束媒楼,不管有沒(méi)有對(duì)應(yīng)關(guān)閉標(biāo)簽存在
AutoClose []string
// Entity字段用于將非標(biāo)準(zhǔn)的實(shí)體名映射到替換的字符串
// parser的行為就好像標(biāo)準(zhǔn)實(shí)體映射存在于本字段乐尊,即使實(shí)際上本字段沒(méi)有:
//
// "lt": "<",
// "gt": ">",
// "amp": "&",
// "apos": "'",
// "quot": `"`,
Entity map[string]string
// CharsetReader字段如果非nil,會(huì)定義一個(gè)函數(shù)來(lái)生成轉(zhuǎn)換字符集的io.Reader划址,
// 將給定的非utf-8字符集轉(zhuǎn)換為utf-8字符集扔嵌。如果CharsetReader字段為nil
// 或者返回一個(gè)錯(cuò)誤,解析將會(huì)停止并發(fā)揮該錯(cuò)誤夺颤。CharsetReader的返回值不能都是nil
CharsetReader func(charset string, input io.Reader) (io.Reader, error)
// DefaultSpace設(shè)置未修飾標(biāo)簽的默認(rèn)名字空間痢缎,就好像整個(gè)XML流都包裝進(jìn)有個(gè)具有屬性
// xmlns="DefaultSpace"的元素內(nèi)
DefaultSpace string
// 內(nèi)含隱藏或非導(dǎo)出字段
}
Decoder代表一個(gè)XML解析器,可以讀取輸入流的部分?jǐn)?shù)據(jù)世澜,該解析器假定輸入是utf-8編碼的独旷。
func NewDecoder
func NewDecoder(r io.Reader) *Decoder
創(chuàng)建一個(gè)從r讀取XML數(shù)據(jù)的解析器。如果r未實(shí)現(xiàn)io.ByteReader接口寥裂,NewDecoder會(huì)為其添加緩存嵌洼。
func (*Decoder) Decode
func (d *Decoder) Decode(v interface{}) error
Decode方法功能類(lèi)似xml.Unmarshal函數(shù),但會(huì)從底層讀取XML數(shù)據(jù)并查找StartElement封恰。
func (*Decoder) DecodeElement
func (d *Decoder) DecodeElement(v interface{}, start *StartElement) error
DecodeElement方法的功能類(lèi)似xml.Unmarshal函數(shù)麻养,但它會(huì)啟出一個(gè)指向XML起始標(biāo)簽后將解析結(jié)果寫(xiě)入v。當(dāng)客戶端自己讀取了一些原始XML token但仍想defer調(diào)用Unmarshal處理一些元素時(shí)很有用诺舔。
func (*Decoder) Token
func (d *Decoder) Token() (t Token, err error)
Token返回輸入流里的下一個(gè)XML token鳖昌。在輸入流的結(jié)尾處备畦,會(huì)返回(nil, io.EOF)
返回的token數(shù)據(jù)里的[]byte數(shù)據(jù)引用自解析器內(nèi)部的緩存,只在下一次調(diào)用Token之前有效遗遵。如要獲取切片的拷貝萍恕,調(diào)用CopyToken函數(shù)或者token的Copy方法。
成功調(diào)用的Token方法會(huì)將自我閉合的元素(如
)擴(kuò)展為分離的起始和結(jié)束標(biāo)簽车要。Token方法會(huì)保證它返回的StartElement和EndElement兩種token正確的嵌套和匹配:如果本方法遇到了不正確的結(jié)束標(biāo)簽允粤,會(huì)返回一個(gè)錯(cuò)誤。
Token方法實(shí)現(xiàn)了XML名字空間翼岁,細(xì)節(jié)參見(jiàn)http://www.w3.org/TR/REC-xml-names/类垫。每一個(gè)包含在Token里的Name結(jié)構(gòu)體,都會(huì)將Space字段設(shè)為URL標(biāo)識(shí)(如果可知的話)琅坡。如果Token遇到未知的名字空間前綴悉患,它會(huì)使用該前綴作為名字空間,而不是報(bào)錯(cuò)榆俺。
func (*Decoder) RawToken
func (d *Decoder) RawToken() (Token, error)
RawToken方法Token方法售躁,但不會(huì)驗(yàn)證起始和結(jié)束標(biāo)簽,也不將名字空間前綴翻譯為它們相應(yīng)的URL茴晋。
func (*Decoder) Skip
func (d *Decoder) Skip() error
Skip從底層讀取token陪捷,直到讀取到最近一次讀取到的起始標(biāo)簽對(duì)應(yīng)的結(jié)束標(biāo)簽。如果讀取中遇到別的起始標(biāo)簽會(huì)進(jìn)行迭代诺擅,因此可以跳過(guò)嵌套結(jié)構(gòu)市袖。如果本方法找到了對(duì)應(yīng)起始標(biāo)簽的結(jié)束標(biāo)簽,會(huì)返回nil烁涌;否則返回一個(gè)描述該問(wèn)題的錯(cuò)誤苍碟。
type Encoder
type Encoder struct {
p printer
}
Encoder向輸出流中寫(xiě)入XML數(shù)據(jù)。
func NewEncoder
func NewEncoder(w io.Writer) *Encoder
NewEncoder創(chuàng)建一個(gè)寫(xiě)入w的*Encoder撮执。
type Address struct {
City, State string
}
type Person struct {
XMLName xml.Name `xml:"person"`
Id int `xml:"id,attr"`
FirstName string `xml:"name>first"`
LastName string `xml:"name>last"`
Age int `xml:"age"`
Height float32 `xml:"height,omitempty"`
Married bool
Address
Comment string `xml:",comment"`
}
func main() {
v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42}
v.Comment = " Need more details. "
v.Address = Address{"Hanga Roa", "Easter Island"}
enc := xml.NewEncoder(os.Stdout)
enc.Indent(" ", " ")
if err := enc.Encode(v); err != nil {
fmt.Printf("error: %v\n", err)
}
}
func (*Encoder) Encode
func (enc *Encoder) Encode(v interface{}) error
Encode將v編碼為XML后寫(xiě)入底層微峰。參見(jiàn)Marshal函數(shù)獲取go到XML轉(zhuǎn)換的細(xì)節(jié)。在返回前enc會(huì)調(diào)用Flush抒钱。
func (*Encoder) EncodeElement
func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error
EncodeElement將v的XML編碼寫(xiě)入底層县忌, 并使用start作為編碼的最外層。參見(jiàn)Marshal函數(shù)獲取go到XML轉(zhuǎn)換的細(xì)節(jié)继效。在返回前enc會(huì)調(diào)用Flush方法。
func (*Encoder) EncodeToken
func (enc *Encoder) EncodeToken(t Token) error
EncodeToken向底層寫(xiě)入一個(gè)token装获。如果StartElement和EndElement的匹配不正確瑞信,本方法會(huì)返回錯(cuò)誤。
EncodeToken 方法不會(huì)調(diào)用Flush穴豫,因?yàn)樗ǔJ歉笮筒僮魅鏓ncode或EncodeElement方法的一部分(或者用戶自定義的Marshaler接口MarshalXML 方法里調(diào)用本方法)凡简,這些方法會(huì)在結(jié)束前Flush逼友。調(diào)用者創(chuàng)建一個(gè)Encoder并直接使用本方法而不使用Encode或EncodeElement方法的話,必須在結(jié)束時(shí)調(diào)用Flush以保證XML數(shù)據(jù)寫(xiě)入底層的io.Writer接口秤涩。
EncodeToken寫(xiě)入ProcInst類(lèi)型Token時(shí)帜乞,只允許在底層流最開(kāi)始寫(xiě)入目標(biāo)是"xml"的ProcInst。
func (*Encoder) Flush
func (enc *Encoder) Flush() error
Flush方法會(huì)將緩存中的XML數(shù)據(jù)寫(xiě)入底層筐眷。參見(jiàn)EncodeToken函數(shù)獲取細(xì)節(jié)信息黎烈。
func (*Encoder) Indent
func (enc *Encoder) Indent(prefix, indent string)
Indent函數(shù)設(shè)定編碼器生成XML數(shù)據(jù)時(shí)的格式化縮進(jìn)信息。細(xì)節(jié)請(qǐng)參見(jiàn)MarshalIndent函數(shù)匀谣。
Bugs
? XML元素和數(shù)據(jù)結(jié)構(gòu)體的映射有天生的缺陷:XML元素是依賴順序的匿名值的集合照棋,而結(jié)構(gòu)體是不依賴順序的命名值的集合。參見(jiàn)json包獲取更適用于數(shù)據(jù)結(jié)構(gòu)體的文本表示武翎。