Go:使用一组json标记解码json,并编码为另一组json标记
我有一个应用程序,它使用来自第三方api的数据。我需要将json解码为一个结构,这要求该结构具有“传入”json字段的json标记。传出的json字段具有不同的命名约定,因此我需要不同的json标记进行编码 我必须用许多不同的结构来完成这项工作,每个结构可能有许多字段 在不重复大量代码的情况下完成此任务的最佳方法是什么? 示例结构:Go:使用一组json标记解码json,并编码为另一组json标记,json,go,Json,Go,我有一个应用程序,它使用来自第三方api的数据。我需要将json解码为一个结构,这要求该结构具有“传入”json字段的json标记。传出的json字段具有不同的命名约定,因此我需要不同的json标记进行编码 我必须用许多不同的结构来完成这项工作,每个结构可能有许多字段 在不重复大量代码的情况下完成此任务的最佳方法是什么? 示例结构: // incoming "schema" field names type AccountIn struct { OpenDate string `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"`
}
如果可以通过
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)
}
}
}
如果您可以通过
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)
}
}
}
一种不常见但可能相当有效的工作方法是使用中间格式,这样您就可以使用不同的读写器,从而使用不同的标记。例如,它允许将嵌套映射结构转换为结构 类型。非常类似于json解组,只是从一个映射
// 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标记。一种不常见但可能相当好的工作方法是使用中间格式,这样您可以使用不同的读写器,从而使用不同的标记。例如,它允许将嵌套映射结构转换为结构 类型。非常类似于json解组,只是从一个映射
// 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)
稍后在编写(或阅读)时,u将直接使用json函数,然后再使用json标记。也许Go 1.8即将进行的更改将对您有所帮助,它将允许“强制转换”类型,即使其json标记定义不同:这在1.8beta上也能正常工作,我想这将简化您当前的解决方案也许Go 1.8即将进行的更改将对您有所帮助,它将允许“强制转换”类型,即使其JSON标记定义不同:这在1.8beta上的效果与预期一样,我想这将简化您当前的解决方案这可能是一种幼稚的方法,但很容易实现:-
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)
这可能是一种幼稚的方法,但很容易实现:-
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)
你有多少事情要重复?如果你没有太多的类型,那么创建多个结构可能会更容易。这太多了。我已经考虑过了,但无法理解那是多么乏味(以及维护噩梦)。因此,我需要比我聪明的人的帮助。计算机擅长繁琐的事情——我可能会为翻译后的类型生成代码。不幸的是,我一时想不出一个干净、通用的解决方案。你要重复多少事情?如果你没有太多的类型,那么创建多个结构可能会更容易。这太多了。我已经考虑过了,但无法理解那是多么乏味(以及维护噩梦)。因此,我需要比我聪明的人的帮助。计算机擅长繁琐的事情——我可能会为翻译后的类型生成代码。不幸的是,我想不出一个干净的、通用的解决方案。这里描述了语言规范的变化,这里描述了语言规范的变化