[英]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.Unmarshal
和json.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)
}
}
}
这可能是一种幼稚的方法,但相当容易实现:
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.