php小編百草今天為大家介紹一個強大的Golang特性-具有不同結構標籤集的Unmarshal。在Golang程式設計中,Unmarshal是一種將資料轉換為結構體的過程。但是,當我們的資料來源包含不同的結構標籤集時,傳統的Unmarshal方法可能無法滿足需求。因此,我們需要使用具有不同結構標籤集的Golang Unmarshal來實現這項功能。本文將詳細介紹這個特性的使用方法和注意事項。讓我們一起來探索吧!
我正在使用第三方工具的 api,它的 json 中包含自訂鍵名稱。我還必須在兩個不同的環境(生產環境和登台環境)上使用 api。不幸的是,api 中的自訂欄位在兩個環境中具有不同的鍵名稱來表示相同的資料。在下面的範例中,生產環境中的 json 金鑰 custom-1
與暫存環境中的 json 金鑰 custom-7
完全相同。我想將其中任何一個解組到相同的資料結構中,但我不知道如何進行。我希望有一種方法可以以某種方式覆寫json.unmarshal()
函數用於在prod 上使用json
的標籤,但在暫存時使用jsonstaging
。對我來說,這是最有意義且最簡單的解決方案。我猜我必須為我的jsonobj
類型編寫一個自定義unmarshaljson(data []byte) error
函數,但同樣,我不知道如何在自定義函數中實現所需的行為。有人能給我指出正確的方向、一些文件或一些我可以使用的範例嗎?
package main import ( "encoding/json" "fmt" ) type jsonobj struct { id string `json:"custom-1" jsonstaging:"custom-7"` desc string `json:"custom-2" jsonstaging:"custom-8"` } func (i jsonobj) string() string { return fmt.sprintf(`{ id: "%s", desc: "%s" }`, i.id, i.desc) } func main() { var jsonprod = `{ "custom-1": "object-a", "custom-2": "test" } ` var jsonstaging = `{ "custom-7": "object-a", "custom-8": "test" } ` var jsonobjprod jsonobj var jsonobjstaging jsonobj json.unmarshal([]byte(jsonprod), &jsonobjprod) json.unmarshal([]byte(jsonstaging), &jsonobjstaging) fmt.println("production: ", jsonobjprod) fmt.println("staging: ", jsonobjstaging) }
當我用 go run 運行它時,我得到
production: { id: "object-a", desc: "test" } staging: { id: "", desc: "" }
這是我目前程式碼所期望的,但我想得到
Production: { Id: "object-a", Desc: "test" } Staging: { Id: "object-a", Desc: "test" }
我無法修改臨時環境或生產環境的 api。
我嘗試過創建不同的結構和接口,但是隨著字段數量(以及自定義 json 鍵)的增加(它們會增加),這似乎是維護的噩夢。如果這是唯一的方法,請幫助我,在我決定這可能不是正確的路徑之前,我也沒有讓它發揮作用。
為了將來參考,如果有人想這樣做,我想我找到了使用內建 reflect
套件的方法。
首先,您必須使用 json.unmarshal() 函數,但填入 map[string] 介面{}
而不是您要建立的物件。
然後我寫了一個獲取環境和地圖的函數。它會遍歷實際物件(而不是地圖)的新實例中的所有字段,並取得您正在使用的環境的標籤。然後它將新物件中的欄位設為 objmap[tag].(<variable_type>)
。使用標籤設定所有欄位後,它將傳回新物件。
這是我的工作程式碼:
package main import ( "encoding/json" "fmt" "reflect" ) const ( StagingStructTag = "jsonStaging" ProductionStructTag = "json" ) type jsonObj struct { Id string `json:"custom-1" jsonStaging:"custom-7"` Desc string `json:"custom-2" jsonStaging:"custom-8"` } func (i jsonObj) String() string { return fmt.Sprintf(`{ Id: "%s", Desc: "%s" }`, i.Id, i.Desc) } func main() { var jsonProd = `{ "custom-1": "object-a", "custom-2": "test" } ` var jsonStaging = `{ "custom-7": "object-a", "custom-8": "test" } ` var env string = "staging" var jsonObjProd jsonObj var jsonObjStaging jsonObj var jsonObjProdMap map[string]interface{} var jsonObjStagingMap map[string]interface{} json.Unmarshal([]byte(jsonStaging), &jsonObjStagingMap) json.Unmarshal([]byte(jsonProd), &jsonObjProdMap) jsonObjStaging = BuildJsonObj(env, jsonObjStagingMap) env = "production" jsonObjProd = BuildJsonObj(env, jsonObjProdMap) fmt.Println("Production: ", jsonObjProd) fmt.Println("Staging: ", jsonObjStaging) } func BuildJsonObj(env string, objMap map[string]interface{}) jsonObj { var obj jsonObj var t reflect.Type = reflect.TypeOf(obj) var structTagName string if env == "staging" { structTagName = StagingStructTag } else if env == "production" { structTagName = ProductionStructTag } for i := 0; i < t.NumField(); i++ { var field reflect.StructField = t.Field(i) var tag string var ok bool if tag, ok = field.Tag.Lookup(structTagName); ok { switch field.Name { case "Id": obj.Id = objMap[tag].(string) case "Desc": obj.Desc = objMap[tag].(string) } } } return obj }
以上是具有不同結構標籤集的 Golang Unmarshal的詳細內容。更多資訊請關注PHP中文網其他相關文章!