dpzff20644 2018-04-30 05:34
浏览 60
已采纳

1个接口,2个程序包,相同的结构变量名称但不同的json命名约定

I am wondering if it is possible in the below scenario to be able to remove the two "Balance" structs in each package and just use the interface based "Balance" struct somehow for unmarshalling. The issue that I have is that the json structure that comes back from the individual api's for Balance is different so as of right now I am just converting the local Balance structs into the global interface based Balance struct and returning that. This method is not ideal especially for more complex but very similar functions that I have. I am sure there is a better way to do this but could not find anything similar. Thanks in advance.

//******************** API Inteface *****************************
//API Interface path: /global/interfaces/apiinterface/apiinterface.go && structs.go
// /global/interfaces/apiinterface/apiinterface.go
type APIInterface interface {
    //.... other interface func(s)
    GetBalance(account string) (balance Balance, err error)
}
// /global/interfaces/apiinterface/structs.go
type Balance struct{
    Available       float64
    Unconfirmed     float64
}


//******************** Library 1 *****************************
//Library 1 path: /library1/library1.go

type jsonResponse struct {
    Success bool            `json:"success"`
    Message string          `json:"message"`
    Result  json.RawMessage `json:"result"`
}
//Library 1 Balance struct /library1/structs.go
type Balance struct {
    Available       float64   `json:"available"` //json name difference <----------
    Unconfirmed     float64   `json:"unconfirmed"` //json name difference <----------
}
//Library 1 GetBalance /library1/library1.go
func (c *Library1) GetBalance(account string) (balance apiinterface.Balance, err error) {

    r, err := c.client.do("getbalance", []interface{}{account})
    if err != nil {
        return
    }
    var response jsonResponse
    if err = json.Unmarshal(r, &response); err != nil {
        return
    }
    var tmpBalance Balance //library 1 Balance struct
    err = json.Unmarshal(response.Result, &tmpBalance)
    if err != nil{
        return
    }
    //convert to global apiinterface struct
    balance = apiinterface.Balance{
        Available:tmpBalance.Available,
        Unconfirmed:tmpBalance.Unconfirmed,
    }

    return
}

//******************** Library 2 *****************************
//Library 2 path: /library2/library2.go

type jsonResponse struct {
    Success bool            `json:"success"`
    Message string          `json:"message"`
    Result  json.RawMessage `json:"result"`
}
//Library 2 Balance struct
type Balance struct {
    Available       float64   `json:"total"` //json name difference <----------
    Unconfirmed     float64   `json:"pending"` //json name difference <----------
}
//Library 2 GetBalance
func (c *Library2) GetBalance(account string) (balance apiinterface.Balance, err error) {

    r, err := c.client.do("getbalance", []interface{}{account})
    if err != nil {
        return
    }
    var response jsonResponse
    if err = json.Unmarshal(r, &response); err != nil {
        return
    }
    var tmpBalance Balance //library 2 Balance struct
    err = json.Unmarshal(response.Result, &tmpBalance)
    if err != nil{
        return
    }
    //convert to global apiinterface struct
    balance = apiinterface.Balance{
        Available:tmpBalance.Available,
        Unconfirmed:tmpBalance.Unconfirmed,
    }

    return
}
  • 写回答

2条回答 默认 最新

  • duanjue7508 2018-05-01 01:37
    关注

    See if something like this does what you need:

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    type jsonResponse struct {
        Success bool    `json:"success"`
        Message string  `json:"message"`
        Result  Balance `json:"result"`
    }
    
    type Balance struct {
        Available   float64
        Unconfirmed float64
    }
    
    func (b *Balance) UnmarshalJSON(data []byte) error {
        m := map[string]float64{}
        if err := json.Unmarshal(data, &m); err != nil {
            return err
        }
    
        for k, v := range m {
            if k == "available" || k == "total" {
                b.Available = v
            } else if k == "unconfirmed" || k == "pending" {
                b.Unconfirmed = v
            }
        }
    
        return nil
    }
    
    func main() {
        tests := []string{
            `{"success":true,"message":"first","result":{"available":42.42,"unconfirmed":0.88}}`,
            `{"success":true,"message":"second","result":{"total":3.14,"pending":0.42}}`,
        }
    
        for _, t := range tests {
            resp := jsonResponse{}
            if err := json.Unmarshal([]byte(t), &resp); err != nil {
                panic(err)
            }
            fmt.Printf("%+v
    ", resp)
        }
    
    }
    

    playground

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?