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条)

报告相同问题?

悬赏问题

  • ¥20 西门子S7-Graph,S7-300
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改