1 интерфейс, 2 пакета, одинаковые имена переменных структуры, но разные соглашения об именах json - PullRequest
0 голосов
/ 30 апреля 2018

Мне интересно, возможно ли в приведенном ниже сценарии удалить две структуры "Balance" в каждом пакете и просто использовать структуру "Balance", основанную на интерфейсе, для демаршаллинга. У меня есть проблема в том, что структура json, которая возвращается из отдельных API для Balance, отличается, поэтому на данный момент я просто преобразовываю локальные структуры Balance в структуру Balance на основе глобального интерфейса и возвращаю ее. Этот метод не идеален, особенно для более сложных, но очень похожих функций, которые у меня есть. Я уверен, что есть лучший способ сделать это, но не смог найти ничего похожего. Заранее спасибо.

//******************** 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 ]

0 голосов
/ 01 мая 2018

Посмотрите, делает ли что-то подобное то, что вам нужно:

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\n", resp)
    }

}

площадка

0 голосов
/ 30 апреля 2018

вы можете попробовать что-то вроде этого:

type Balance struct {
    *Balance1
    *Balance2
}

и затем проверьте их с помощью nil, затем приведите не ноль к вашему интерфейсу

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...