jjzjj

json - 1 个接口(interface),2 个包,相同的结构变量名称但不同的 json 命名约定

coder 2024-07-09 原文

我想知道在下面的场景中是否有可能删除每个包中的两个“Balance”结构,并以某种方式使用基于接口(interface)的“Balance”结构进行解码。我遇到的问题是,从各个 api 返回的 json 结构对于 Balance 是不同的,所以现在我只是将本地 Balance 结构转换为基于全局接口(interface)的 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
}

最佳答案

看看这样的东西是否满足您的需要:

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

}

playground

关于json - 1 个接口(interface),2 个包,相同的结构变量名称但不同的 json 命名约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50094483/

有关json - 1 个接口(interface),2 个包,相同的结构变量名称但不同的 json 命名约定的更多相关文章

  1. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  2. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  3. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  4. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  5. ruby-on-rails - 如何重命名或移动 Rails 的 README_FOR_APP - 2

    当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?

  6. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

    我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

  7. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

  8. ruby-on-rails - 如何使用 Rack 接收 JSON 对象 - 2

    我有一个非常简单的RubyRack服务器,例如:app=Proc.newdo|env|req=Rack::Request.new(env).paramspreq.inspect[200,{'Content-Type'=>'text/plain'},['Somebody']]endRack::Handler::Thin.run(app,:Port=>4001,:threaded=>true)每当我使用JSON对象向服务器发送POSTHTTP请求时:{"session":{"accountId":String,"callId":String,"from":Object,"headers":

  9. ruby - Rack:如何将 URL 存储为变量? - 2

    我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.

  10. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

随机推荐