Heim  >  Artikel  >  Backend-Entwicklung  >  Golang Unmarshal mit unterschiedlichen Struktur-Tags

Golang Unmarshal mit unterschiedlichen Struktur-Tags

WBOY
WBOYnach vorne
2024-02-09 23:10:09520Durchsuche

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

php-Editor Baicao stellt Ihnen heute eine leistungsstarke Golang-Funktion vor – Unmarshal mit verschiedenen strukturellen Tag-Sets. In der Golang-Programmierung ist Unmarshal ein Prozess zum Konvertieren von Daten in eine Struktur. Wenn unsere Datenquelle jedoch unterschiedliche Sätze struktureller Tags enthält, erfüllt die herkömmliche Unmarshal-Methode möglicherweise nicht die Anforderungen. Daher müssen wir Golang Unmarshal mit einem anderen Satz struktureller Tags verwenden, um diese Funktionalität zu erreichen. In diesem Artikel werden die Verwendung und Vorsichtsmaßnahmen dieser Funktion ausführlich vorgestellt. Lasst uns gemeinsam erkunden!

Frageninhalt

Ich verwende die API eines Drittanbieter-Tools und deren JSON enthält benutzerdefinierte Schlüsselnamen. Ich muss die API auch in zwei verschiedenen Umgebungen verwenden (Produktion und Staging). Leider haben die benutzerdefinierten Felder in der API in beiden Umgebungen unterschiedliche Schlüsselnamen, um dieselben Daten darzustellen. Im folgenden Beispiel funktioniert der JSON-Schlüssel custom-1 与暂存环境中的 json 密钥 custom-7 完全相同。我想将其中任何一个解组到相同的数据结构中,但我不知道如何进行。我希望有一种方法可以以某种方式覆盖 json.unmarshal() 函数用于在 prod 上使用 json 的标签,但在暂存时使用 jsonstaging 。对我来说,这是最有意义且最简单的解决方案。我猜我必须为我的 jsonobj 类型编写一个自定义 unmarshaljson(data []byte) error in der Produktion, aber auch hier weiß ich nicht, wie ich das gewünschte Verhalten in einer benutzerdefinierten Funktion erreichen kann. Kann mir jemand den richtigen Weg weisen, eine Dokumentation oder Beispiele, die ich verwenden kann?

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)
}

Wenn ich es mit „Go Run“ ausführe, erhalte ich

production:  { id: "object-a", desc: "test" }
staging:  { id: "", desc: "" }

Das ist es, was mein aktueller Code erwartet, aber ich würde gerne bekommen

Production:  { Id: "object-a", Desc: "test" }
Staging:  { Id: "object-a", Desc: "test" }

Ich kann die API der Staging- oder Produktionsumgebung nicht ändern.

Ich habe versucht, verschiedene Strukturen und Schnittstellen zu erstellen, aber da die Anzahl der Felder (und benutzerdefinierten JSON-Schlüssel) zunimmt (und wächst), scheint es ein Wartungsalptraum zu sein. Bitte helfen Sie mir, wenn dies der einzige Weg ist. Ich habe es auch nicht zum Laufen gebracht, bevor ich entschieden habe, dass dies möglicherweise nicht der richtige Weg ist.

Problemumgehung

Falls jemand dies in Zukunft tun möchte, denke ich, dass ich einen Weg gefunden habe, das integrierte reflect-Paket zu verwenden.

Zuerst müssen Sie die Funktion json.unmarshal() verwenden, aber map[string] 接口{} anstelle des Objekts eingeben, das Sie erstellen möchten.

Dann habe ich eine Funktion geschrieben, die die Umgebung und die Karte abruft. Es durchläuft alle Felder in der neuen Instanz des tatsächlichen Objekts (nicht der Karte) und ruft die Bezeichnung für die von Ihnen verwendete Umgebung ab. Anschließend werden die Felder im neuen Objekt auf objmap[tag].(f215d538f93896d2fa3ea4137b420524) gesetzt. Nachdem alle Felder mit Beschriftungen versehen wurden, wird das neue Objekt zurückgegeben.

Das ist mein Arbeitscode:

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
}

Das obige ist der detaillierte Inhalt vonGolang Unmarshal mit unterschiedlichen Struktur-Tags. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen