Home >Backend Development >Golang >Golang Unmarshal with different set of structural tags
php editor Baicao today introduces to you a powerful Golang feature - Unmarshal with different structural tag sets. In Golang programming, Unmarshal is a process of converting data into a structure. However, when our data source contains different sets of structural tags, the traditional Unmarshal method may not meet the needs. Therefore, we need to use Golang Unmarshal with a different set of structural tags to achieve this functionality. This article will introduce in detail the usage and precautions of this feature. Let’s explore together!
I am using a third party tool's api which has custom key names in its json. I also have to use the api on two different environments (production and staging). Unfortunately, the custom fields in the api have different key names in both environments to represent the same data. In the example below, the json key custom-1
in the production environment is exactly the same as the json key custom-7
in the staging environment. I want to unmarshal any of them into the same data structure but I don't know how. I was hoping there was a way to somehow override the json.unmarshal()
function for tags that use json
on prod, but use jsonstaging# when staging ##. To me, this makes the most sense and is the simplest solution. I guess I'll have to write a custom
unmarshaljson(data []byte) error function for my
jsonobj type, but again, I don't know how to achieve what I want in a custom function the behavior of. Can anyone point me in the right direction, some documentation, or some examples I can use?
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) }When I run it with go run I get
production: { id: "object-a", desc: "test" } staging: { id: "", desc: "" }This is what my current code is expecting, but I would like to get
Production: { Id: "object-a", Desc: "test" } Staging: { Id: "object-a", Desc: "test" }I cannot modify the api of the staging or production environment.
I've tried creating different structures and interfaces, but as the number of fields (and custom json keys) increases (and they grow) it seems to be a maintenance nightmare. Please help me if this is the only way, I didn't get it to work either before I decided this might not be the right path. WorkaroundFor future reference, if anyone wants to do this, I think I found a way using the built-in
reflect package.
map[string] interface{} instead of the object you want to build.
objmap[tag].(f215d538f93896d2fa3ea4137b420524). After setting all the fields with labels it will return the new object.
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 }
The above is the detailed content of Golang Unmarshal with different set of structural tags. For more information, please follow other related articles on the PHP Chinese website!