亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用 \u0000 \x00 去 json.Unmarshal 鍵

使用 \u0000 \x00 去 json.Unmarshal 鍵

Go
收到一只叮咚 2021-11-08 10:31:36
這是 Go游樂場鏈接?;旧?#39;\u0000',我的 JSON 字符串鍵中有一些特殊字符 ( ):var j = []byte(`{"Page":1,"Fruits":["5","6"],"\u0000*\u0000_errorMessages":{"x":"123"},"*_successMessages":{"ok":"hi"}}`)我想將它解組為一個結構:type Response1 struct {    Page   int    Fruits []string    Msg    interface{} `json:"*_errorMessages"`    Msg1   interface{} `json:"\\u0000*\\u0000_errorMessages"`    Msg2   interface{} `json:"\u0000*\u0000_errorMessages"`    Msg3   interface{} `json:"\0*\0_errorMessages"`    Msg4   interface{} `json:"\\0*\\0_errorMessages"`    Msg5   interface{} `json:"\x00*\x00_errorMessages"`    Msg6   interface{} `json:"\\x00*\\x00_errorMessages"`    SMsg   interface{} `json:"*_successMessages"`}我嘗試了很多,但它不起作用。此鏈接可能對golang.org/src/encoding/json/encode_test.go有所幫助。
查看完整描述

3 回答

?
哈士奇WWW

TA貢獻1799條經驗 獲得超6個贊

簡短回答:在當前的json實現中,不可能只使用struct tags。


注意:這是一個實現限制,而不是規范限制。(這是json包實現的限制,而不是結構標簽規范的限制。)


一些背景:您使用原始字符串文字指定了標簽:


原始字符串文字的值是由引號之間的未解釋(隱式 UTF-8 編碼)字符組成的字符串...


因此,編譯器不會在原始字符串文字的內容中進行轉義或取消引用。


引用自 struct 標記值的約定reflect.StructTag:


按照慣例,標簽字符串是可選的空格分隔鍵:“值”對的串聯。每個鍵都是一個非空字符串,由除空格 (U+0020 ' ')、引號 (U+0022 '"') 和冒號 (U+003A ':') 以外的非控制字符組成。每個值都用引號引起來使用 U+0022 '"' 字符和 Go 字符串文字語法。


這意味著按照慣例標簽值是由空格分隔的 (key:"value") 對列表。有鑰匙不少限制,但值可以是任何東西,和值(應該)使用“去串文字語法”,這意味著這些值將在運行時從代碼中加引號(通過一個電話strconv.Unquote(),叫from StructTag.Get(),在源文件reflect/type.go,當前行 #809)。


所以不需要雙引號。請參閱您的簡化示例:


type Response1 struct {

    Page   int

    Fruits []string

    Msg    interface{} `json:"\u0000_abc"`

}

現在下面的代碼:


t := reflect.TypeOf(Response1{})

fmt.Printf("%#v\n", t.Field(2).Tag)

fmt.Printf("%#v\n", t.Field(2).Tag.Get("json"))

印刷:


"json:\"\\u0000_abc\""

"\x00_abc"

如您所見,json鍵的值部分是"\x00_abc"正確包含零字符的。


但是json包將如何使用它?


該json包使用返回的值StructTag.Get()(從reflect包裝),正是我們所做的。您可以在json/encode.go源文件typeFields()函數中看到它,當前行 #1032。到現在為止還挺好。


然后它調用源文件中未導出的json.parseTag()函數json/tags.go,當前行#17。這會剪切逗號后面的部分(成為“標簽選項”)。


最后json.isValidTag()使用源文件中的前一個值調用函數json/encode.go,當前行#731。此函數檢查傳遞的符文string,并且(除了一組預定義的允許字符"!#$%&()*+-./:<=>?@[]^_{|}~ ")拒絕不是 Unicode 字母或數字(由unicode.IsLetter()和定義unicode.IsDigit())的所有內容:


if !unicode.IsLetter(c) && !unicode.IsDigit(c) {

    return false

'\u0000' 不是預定義的允許字符的一部分,您現在可以猜到,它既不是字母也不是數字:


// Following code prints "INVALID":

c := '\u0000'

if !unicode.IsLetter(c) && !unicode.IsDigit(c) {

    fmt.Println("INVALID")

}

并且由于isValidTag()返回false,name(這是json鍵的值,沒有“標簽選項”部分)將被丟棄(name = "")并且不被使用。因此,將找不到包含 unicode 零的 struct 字段的匹配項。


對于替代解決方案,請使用map、自定義json.Unmarshaler或使用json.RawMessage。


但我非常不鼓勵使用這種丑陋的 json 鍵。我知道您可能只是想解析這樣的 json 響應,它可能超出您的范圍,但是您應該反對使用這些鍵,因為它們只會在以后引起更多問題(例如,如果存儲在 db 中,通過檢查記錄它會很難發現其中有'\u0000'字符,因為它們可能會顯示為空)。


查看完整回答
反對 回復 2021-11-08
?
largeQ

TA貢獻2039條經驗 獲得超8個贊

我認為 struct 標簽不可能做到這一點。您可以做的最好的事情是將其解組map[string]interface{},然后手動獲取值:


var b = []byte(`{"\u0000abc":42}`)

var m map[string]interface{}

err := json.Unmarshal(b, &m)

if err != nil {

    panic(err)

}

fmt.Println(m, m["\x00abc"])

游樂場:http : //play.golang.org/p/RtS7Nst0d7。


查看完整回答
反對 回復 2021-11-08
?
青春有我

TA貢獻1784條經驗 獲得超8個贊

由于以下原因,您不能這樣做:http : //golang.org/ref/spec#Struct_types

但是您可以解組,map[string]interface{}然后通過regexp檢查該對象的字段名稱。


查看完整回答
反對 回復 2021-11-08
  • 3 回答
  • 0 關注
  • 444 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號