繁体   English   中英

开始:使用一组json标签解码json,并编码为另一组json标签

[英]Go: decoding json with one set of json tags, and encoding to a different set of json tags

我有一个使用第三方API数据的应用程序。 我需要将json解码为一个结构,这要求该结构具有“传入” json字段的json标签。 传出的json字段具有不同的命名约定,因此我需要使用不同的json标签进行编码。

我将不得不使用许多不同的结构来执行此操作,并且每个结构可能具有许多字段。

在不重复大量代码的情况下实现此目标的最佳方法是什么?

示例结构:

// incoming "schema" field names
type AccountIn struct {
    OpenDate string `json:"accountStartDate"`
    CloseDate string `json:"cancelDate"`
}


// outgoing "schema" field names
type AccountOut struct {
    OpenDate string `json:"openDate"`
    CloseDate string `json:"closeDate"`
} 

一种不常见但可能很好的工作方法是使用一种中间格式,以便您可以使用不同的读取器和写入器,因此可以使用不同的标签。 例如https://github.com/mitchellh/mapstructure ,它允许将嵌套的地图结构转换为结构类型。 就像json unmarshal一样,仅来自地图。

// incoming "schema" field names
type AccountIn struct {
    OpenDate string `mapstructure:"accountStartDate" json:"openDate"`
    CloseDate string `mapstructure:"cancelDate" json:"closeDate"`
}

// from json to map with no name changes
temporaryMap := map[string]interface{}{}
err := json.Unmarshal(jsonBlob, &temporaryMap)

// from map to structs using mapstructure tags
accountIn := &AccountIn{}
mapstructure.Decode(temporaryMap, accountIn)

稍后在写(或读)时,您将直接使用json函数,然后将使用json标签。

可能即将进行的Go 1.8更改会为您提供帮助,即使JSON标签定义不同,它也可以“投射”类型: https : //play.golang.org/p/Xbsoa8SsEk可以在1.8beta上正常运行,我猜想这将简化您当前的解决方案

如果可以再遍历json.Unmarshaljson.Marshal ,并且在各种类型中都没有任何模棱两可的字段名称,则可以通过将所有json键解编为由json包:

// map incoming to outgoing json identifiers
var translation = map[string]string{
    "accountStartDate": "openDate",
    "cancelDate":       "closeDate",
}

func translateJS(js []byte) ([]byte, error) {
    var m map[string]interface{}
    if err := json.Unmarshal(js, &m); err != nil {
        return nil, err
    }

    translateKeys(m)
    return json.MarshalIndent(m, "", "  ")
}

func translateKeys(m map[string]interface{}) {
    for _, v := range m {
        if v, ok := v.(map[string]interface{}); ok {
            translateKeys(v)
        }
    }

    keys := make([]string, 0, len(m))
    for k := range m {
        keys = append(keys, k)
    }

    for _, k := range keys {
        if newKey, ok := translation[k]; ok {
            m[newKey] = m[k]
            delete(m, k)
        }
    }
}

https://play.golang.org/p/nXmWlj7qH9

这可能是一种幼稚的方法,但相当容易实现:

func ConvertAccountInToAccountOut(AccountIn incoming) (AccountOut outcoming){
    var outcoming AccountOut
    outcoming.OpenDate = incoming.OpenDate
    outcoming.CloseDate = incoming.CloseDate

    return outcoming
}

var IncomingJSONData AccountIn
resp := getJSONDataFromSource()  // Some method that gives you the Input JSON
err1 := json.UnMarshall(resp,&IncomingJSONData)
OutGoingJSONData := ConvertAccountInToAccountOut(IncomingJSONData)

if err1 != nil {
    fmt.Println("Error in UnMarshalling JSON ",err1)
}

fmt.Println("Outgoing JSON Data: ",OutGoingJSONData)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM