首頁  >  文章  >  後端開發  >  具有不同結構標籤集的 Golang Unmarshal

具有不同結構標籤集的 Golang Unmarshal

WBOY
WBOY轉載
2024-02-09 23:10:09526瀏覽

具有不同结构标签集的 Golang Unmarshal

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].(f215d538f93896d2fa3ea4137b420524)。使用標籤設定所有欄位後,它將傳回新物件。

這是我的工作程式碼:

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中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除