GoLang中Json?Tag用法實(shí)例總結(jié)
前言
GoLang中結(jié)構(gòu)體的 JSON Tag 標(biāo)識(shí)(英文名backquote或backtick,反引號(hào) ` 符號(hào)包裹的部分內(nèi)容)一直未明確看過(guò)完整規(guī)范和使用說(shuō)明,存在模棱兩可,系統(tǒng)整理如下:
- JSON Tag標(biāo)簽的完整語(yǔ)法,包含哪些選項(xiàng)
- 不同選項(xiàng)(輸出名/-/omitempty/string)的作用及使用范圍
- 特殊注意事項(xiàng)補(bǔ)充
Json中Tag用法匯總
- JSON Tag標(biāo)簽格式為:
json:"FieldName/-/可選,omitempty/可選,string/可選
- 多個(gè)選項(xiàng)之間使用 , 逗號(hào)分割
- FieldName選項(xiàng):指定編碼后鍵名稱(chēng)
- 可為空,則使用Struct對(duì)應(yīng)字段名作為JSON輸出名
- FieldName非空,則使用指定的FieldName作為JSON輸出名
- -符號(hào),輸出時(shí)忽略此字段;但要注意-,(多一個(gè)逗號(hào)結(jié)尾)時(shí),輸出字段名為-的JSON字段,而不是忽略
- omitempty選項(xiàng):忽略空值
- 包含此選項(xiàng),輸出時(shí)字段空值(零值+空值:false、0、nil指針、nil接口值,以及任何空數(shù)組、切片、map或字符串)則不輸出
- string選項(xiàng):結(jié)果輸出為字符串
- 字段結(jié)果輸出為字符串
- 只適用于字符串、浮點(diǎn)、整數(shù)或布爾類(lèi)型的字段
- 這種額外的編碼有時(shí)在與 JavaScript 程序通信時(shí)使用
- 要注意,如果字段值本身為string時(shí),再次增加JSON的string標(biāo)簽選項(xiàng),會(huì)導(dǎo)致多個(gè)引號(hào)的情況
// 示例代碼:https://go.dev/play/p/ApzFQttV_MB package main import ( ?? ?"encoding/json" ?? ?"fmt" ?? ?"os" ) func main() { ?? ?type ColorGroup struct { ?? ??? ?Hello ? bool ? ? `json:"Hello,string"` ?? ??? ?world ? bool ? ? `json:"World,string"` ?? ??? ?ID ? ? ?int ? ? ?`json:"id,string"` ?? ??? ?Name ? ?string ? `json:"name,string"` ?? ??? ?Colors ?[]string `json:"ColorName,omitempty"` ?? ??? ?Colors1 []string `json:"ColorName1"` ?? ??? ?Colors2 []string `json:"ColorName2"` ?? ?} ?? ?group := ColorGroup{ ?? ??? ?Hello: ? true, ?? ??? ?world: ? true, ?? ??? ?ID: ? ? ?1, ?? ??? ?Name: ? ?"Reds", ?? ??? ?Colors: ?[]string{"hello", "world"}, ?? ??? ?Colors1: nil, ?? ??? ?Colors2: []string{}, ?? ?} ?? ?b, err := json.Marshal(group) ?? ?if err != nil { ?? ??? ?fmt.Println("error:", err) ?? ?} ?? ?os.Stdout.Write(b) } // 輸出結(jié)果 //{"Hello":"true","id":"1","name":"\"Reds\"","ColorName":["hello","world"],"ColorName1":null,"ColorName2":[]}
其他注意:
- nil 指針、nil 接口、nil切片等nil類(lèi)型值,進(jìn)行編碼后為 null JSON 對(duì)象
- 空切片、空數(shù)組編碼為 [] JSON 數(shù)組
- map 編碼為 {} JSON 對(duì)象
- 指針類(lèi)型值編碼為指針?biāo)赶虻闹担涌陬?lèi)型值編碼后為對(duì)應(yīng)類(lèi)型的值
官方 Marshal 函數(shù)說(shuō)明
func Marshal(v interface{}) ([]byte, error)
Marshal 返回變量 v 的 JSON 編碼后結(jié)果
Marshal 函數(shù)會(huì)遞歸的處理變量 v;如果一個(gè)值實(shí)現(xiàn)了Marshaler接口,并且不是一個(gè)nil指針,Marshal 調(diào)用其 MarshalJSON 方法來(lái)生成 JSON 數(shù)據(jù)。如果沒(méi)有 MarshalJSON 方法但實(shí)現(xiàn)了 encoding.TextMarshaler 方法,Marshal 調(diào)用 MarshalText 方法并將結(jié)果編碼為 JSON 字符串。nil 指針異常并不是嚴(yán)格意義上的必須,而是模仿了UnmarshalJSON行為中的一個(gè)類(lèi)似的、必須的異常。
否則,Marshal使用以下與類(lèi)型有關(guān)的默認(rèn)編碼:
- 布爾值被編碼為JSON布爾值
- 浮點(diǎn)、整數(shù)和數(shù)值類(lèi)型值編碼為JSON數(shù)字
- 字符串值被編碼為JSON字符串,被強(qiáng)制為有效的UTF-8,用Unicode替換符文替換無(wú)效的字節(jié)。為了使JSON能夠安全地嵌入到HTML <script>標(biāo)簽中,字符串使用HTMLEscape進(jìn)行編碼,將”<”、”>”、”&”、”U+2028”和”U+2029”轉(zhuǎn)義為”\u003c”、”\u003e”、”\u0026”、”\u2028”、和”\u2029”。在使用編碼器時(shí),可以通過(guò)調(diào)用SetEscapeHTML(false)禁用這種替換。
- 數(shù)組和分片的值會(huì)被編碼為JSON數(shù)組,但[]byte會(huì)被編碼為base64編碼的字符串,而nil切片會(huì)被編碼為null JSON對(duì)象值。
- 數(shù)組、分片,編碼后為 JSON 數(shù)組
- []byte空切片,編碼后為空數(shù)組 []
- nil 切片,編碼后為 null
- 結(jié)構(gòu)體類(lèi)型的值被編碼為JSON對(duì)象。每個(gè)導(dǎo)出的結(jié)構(gòu)字段都會(huì)成為對(duì)象的成員,使用字段名作為對(duì)象的鍵,除非字段因?yàn)橄旅娴脑虮皇÷?ul>
- 每個(gè)結(jié)構(gòu)字段的編碼都可通過(guò)存儲(chǔ)在結(jié)構(gòu)字段Tag標(biāo)簽的 “json” 鍵下的格式字符串來(lái)定制。格式字符串給出了字段的名稱(chēng),后面可能有一個(gè)用逗號(hào)分隔的選項(xiàng)列表。名稱(chēng)可以是空的,以便指定選項(xiàng)而不覆蓋默認(rèn)的字段名
- “omitempty”選項(xiàng),如果字段為空值,應(yīng)該從編碼中省略,定義為false、0、nil指針、nil接口值,以及任何空數(shù)組、切片、map或字符串
- 作為一種特殊情況,如果字段標(biāo)簽是”-“,字段總是被省略的。請(qǐng)注意,一個(gè)名稱(chēng)為”-“的字段仍然可以使用標(biāo)簽”-,”來(lái)生成
結(jié)構(gòu)體字段Tag標(biāo)簽下 json 鍵對(duì)應(yīng)格式化字符串說(shuō)明:
- 給出字段編碼后的名稱(chēng),后面可能有一組逗號(hào)分割的選項(xiàng)列表
- 字段名稱(chēng)可以為空,用于在不覆蓋默認(rèn)字段名的情況下指定不同選項(xiàng)
- omitempty選項(xiàng),字段為空值(false/0/nil指針/nil接口值/空數(shù)組/空切片/空map/空字符串)時(shí)則跳過(guò)編碼輸出
- 字段標(biāo)簽為-時(shí),此字段總是被忽略;但要注意,名為-的字段出現(xiàn)在-,標(biāo)簽中時(shí)仍可以被生成
結(jié)構(gòu)體字段標(biāo)簽和對(duì)應(yīng)含義的一些例子:
// Field appears in JSON as key "myName". // 該字段出現(xiàn)在JSON中時(shí),名為"myName" Field int `json:"myName"` // Field appears in JSON as key "myName" and // the field is omitted from the object if its value is empty, // as defined above. // 該字段出現(xiàn)在JSON中時(shí),名為"myName",如為零值則輸出時(shí)忽略此字段 Field int `json:"myName,omitempty"` // Field appears in JSON as key "Field" (the default), but // the field is skipped if empty. // Note the leading comma. // 該字段出現(xiàn)在JSON中時(shí),名為"Field",如為零值則輸出時(shí)忽略此字段 Field int `json:",omitempty"` // Field is ignored by this package. // 該字段當(dāng)前包輸出JSON時(shí)忽略 Field int `json:"-"` // Field appears in JSON as key "-". // 該字段出現(xiàn)在JSON中時(shí),名為"-" Field int `json:"-,"`
"string" 選項(xiàng)表示字段以 JSON 格式存儲(chǔ)在 JSON 編碼的字符串中。它只適用于字符串、浮點(diǎn)、整數(shù)或布爾類(lèi)型的字段。這種額外的編碼有時(shí)在與JavaScript程序通信時(shí)使用。
Int64String int64 `json:",string"`
鍵名滿足以下條件時(shí)將被使用:非空字符串,僅由Unicode字母、數(shù)字和ASCII標(biāo)點(diǎn)符號(hào)(不包括引號(hào)、反斜杠和逗號(hào))組成。
受下文所述的Go可見(jiàn)性規(guī)則的限制,匿名結(jié)構(gòu)字段通常可被編碼,其內(nèi)部可導(dǎo)出的字段等價(jià)于外部結(jié)構(gòu)中的字段。匿名結(jié)構(gòu)體字段使用其JSON Tag標(biāo)簽中給出名稱(chēng),而不是匿名的。接口類(lèi)型的匿名結(jié)構(gòu)字段的處理方式與將該類(lèi)型作為其名稱(chēng)相同,也不是匿名。
在決定對(duì)哪個(gè)字段進(jìn)行marshal或unmarshal時(shí),Go中結(jié)構(gòu)體字段可見(jiàn)性規(guī)則進(jìn)行了調(diào)整。如果在同一級(jí)別有多個(gè)字段,并且該級(jí)別是嵌套最少的(且將是通常Go規(guī)則所選擇的嵌套級(jí)別),則適用以下額外規(guī)則:
1) 在這些字段中,如果有任何字段是JSON Tag標(biāo)記的,就只考慮有標(biāo)記的字段,即使有多個(gè)未標(biāo)記的字段,否則會(huì)發(fā)生沖突。
2) 如果只有一個(gè)字段(根據(jù)第一條規(guī)則標(biāo)記或不標(biāo)記),該字段被選中。
3) 否則有多個(gè)字段,都會(huì)被忽略;不會(huì)發(fā)生錯(cuò)誤。
Go 1.1中新增了對(duì)匿名結(jié)構(gòu)字段的處理。在Go 1.1之前,匿名結(jié)構(gòu)字段被忽略。要在當(dāng)前版本和早期版本中強(qiáng)制忽略匿名結(jié)構(gòu)字段,請(qǐng)給該字段一個(gè)”-“的JSON標(biāo)簽。
Map的值被編碼為JSON對(duì)象。地圖的鍵類(lèi)型必須是字符串、整數(shù)類(lèi)型,或者實(shí)現(xiàn)了encoding.TextMarshaler接口。通過(guò)應(yīng)用以下規(guī)則對(duì)Map的鍵進(jìn)行排序并作為JSON對(duì)象的鍵使用,但要遵守上面為字符串值描述的UTF-8強(qiáng)制規(guī)則。
- 任何字符串類(lèi)型的鍵都可以直接使用
- encoding.TextMarshalers 將被編碼
- 整數(shù)鍵被轉(zhuǎn)換為字符串
指針類(lèi)型值被編碼為所指向的值,一個(gè) nil 指針會(huì)被編碼為 null JSON值。
接口類(lèi)型值編碼為接口中包含的值,一個(gè) nil 接口值被編碼為 null JSON值。
通道(Channel)、復(fù)合類(lèi)型(complex)和函數(shù)值(function)不能進(jìn)行JSON編碼,試圖對(duì)這樣的值進(jìn)行編碼會(huì)導(dǎo)致Marshal返回一個(gè)UnsupportedTypeError錯(cuò)誤。
JSON不能代表循環(huán)嵌套的數(shù)據(jù)結(jié)構(gòu),Marshal函數(shù)也將不處理它們。向Marshal傳遞循環(huán)結(jié)構(gòu)將導(dǎo)致一個(gè)錯(cuò)誤。
參考
總結(jié)
到此這篇關(guān)于GoLang中Json Tag用法的文章就介紹到這了,更多相關(guān)GoLang中Json Tag用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang對(duì)sqlite3數(shù)據(jù)庫(kù)進(jìn)行操作實(shí)踐記錄
sqlite是嵌入式關(guān)系型數(shù)據(jù)庫(kù)引擎,官方描述為自包含的、無(wú)服務(wù)的、零配置并支持事務(wù)的關(guān)系型數(shù)據(jù)庫(kù)引擎,下面這篇文章主要給大家介紹了關(guān)于Golang對(duì)sqlite3數(shù)據(jù)庫(kù)進(jìn)行操作的相關(guān)資料,需要的朋友可以參考下2024-03-03go浮點(diǎn)數(shù)轉(zhuǎn)字符串保留小數(shù)點(diǎn)后N位的完美解決方法
這篇文章主要介紹了go浮點(diǎn)數(shù)轉(zhuǎn)字符串保留小數(shù)點(diǎn)后N位解決辦法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05Golang實(shí)現(xiàn)四層負(fù)載均衡的示例代碼
做開(kāi)發(fā)的同學(xué)應(yīng)該經(jīng)常聽(tīng)到過(guò)負(fù)載均衡的概念,今天我們就來(lái)實(shí)現(xiàn)一個(gè)乞丐版的四層負(fù)載均衡,并用它對(duì)mysql進(jìn)行負(fù)載均衡測(cè)試,感興趣的可以了解一下2023-07-07golang連接redis庫(kù)及基本操作示例過(guò)程
這篇文章主要介紹了golang連接redis庫(kù)及基本操作示例過(guò)程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04深入解析Go語(yǔ)言編程中slice切片結(jié)構(gòu)
這篇文章主要介紹了Go語(yǔ)言編程中slice切片結(jié)構(gòu),其中Append方法的用法介紹較為詳細(xì),需要的朋友可以參考下2015-10-10