JSON-RPC,"无法解组对象"

时间:2017-07-03 18:50:26

标签: json go marshalling rpc json-rpc

我正在尝试学习JSON-RPC如何工作,并使用Go语言(golang)进行测试。 Go程序运行正常。它做它应该做的事情。但是当我尝试通过telnet发出一个原始请求时,它会出错。

这里描述了工作和超级简单的JSON-RPC服务器:

    // rpc_json_server.go

    package main

    import (
        "log"
        "net"
        "net/http"
        "net/rpc"
        "net/rpc/jsonrpc"
    )

    //------------------------------------------------------------------------------
    // Types
    //------------------------------------------------------------------------------

    type Arithmetic int // Used as RPC Service called 'Arithmetic'

    type Arguments struct {
        A int
        B int
    }

    type Result int

    //------------------------------------------------------------------------------
    // Methods
    //------------------------------------------------------------------------------

    func (t *Arithmetic) Multiply(args *Arguments, res *Result) error {

        *res = Result(args.A * args.B)

        return nil
    }

    //------------------------------------------------------------------------------

    func main() {

        var srv *rpc.Server
        var err error
        var arith *Arithmetic
        var listener net.Listener
        var codec rpc.ServerCodec
        var srv_conntype, srv_host, srv_port, srv_addr, srv_path string
        var srv_debugPath string
        var connection net.Conn

        srv_conntype = "tcp"
        srv_host = "0.0.0.0"
        srv_port = "3000"
        srv_addr = srv_host + ":" + srv_port
        srv_path = "/"
        srv_debugPath = "/debug"

        // Create Server, register Service
        srv = rpc.NewServer()
        arith = new(Arithmetic)
        err = srv.Register(arith)
        if err != nil {
            log.Fatalf("Error. Service Format is not correct. %s\r\n", err) //dbg
        }

        // Handle, listen
        srv.HandleHTTP(srv_path, srv_debugPath)
        listener, err = net.Listen(srv_conntype, srv_addr)
        if err != nil {
            log.Fatalf("Error. Can not listen on %s. %s\r\n", srv_addr, err) //dbg
        }
        log.Printf("Started RPC Handler at %s.\r\n", srv_addr) //dbg

        // Serve
        for {

            connection, err = listener.Accept()
            if err != nil {
                log.Fatal(err)
            }

            codec = jsonrpc.NewServerCodec(connection)

            go srv.ServeCodec(codec)
        }

        err = http.Serve(listener, nil)
        if err != nil {
            log.Fatalf("Serve Error. %s\r\n", err) //dbg
        }
    }

    //------------------------------------------------------------------------------

工作和超级简单的JSON-RPC客户端代码如下:

    // rpc_json_client.go

    package main

    import (
        "fmt"
        "log"
        "net"
        "net/rpc"
        "net/rpc/jsonrpc"
    )

    //------------------------------------------------------------------------------
    // Types
    //------------------------------------------------------------------------------

    type Arithmetic int // Used as RPC Service called 'Arithmetic'

    type Arguments struct {
        A int
        B int
    }

    type Result int

    //------------------------------------------------------------------------------
    // Methods
    //------------------------------------------------------------------------------

    func main() {

        var err error
        var srv_conntype, srv_host, srv_port, srv_addr string
        //var srv_path string
        var client *rpc.Client
        var args Arguments
        var result Result
        var serviceName, methodName, funcName string
        var connection net.Conn

        srv_conntype = "tcp"
        srv_host = "0.0.0.0"
        srv_port = "3000"
        srv_addr = srv_host + ":" + srv_port
        //srv_path = "/"

        // Connect to RPC Server
        connection, err = net.Dial(srv_conntype, srv_addr)
        if err != nil {
            log.Fatalf("Error. Can not connect to %s. %s\r\n", srv_addr, err) //dbg
        }
        defer connection.Close()

        // Client
        client = jsonrpc.NewClient(connection)

        // Prepare Call
        serviceName = "Arithmetic"
        methodName = "Multiply"
        funcName = serviceName + "." + methodName
        args.A = 7
        args.B = 8

        // Call remote Procedure
        err = client.Call(funcName, args, &result)
        if err != nil {
            log.Fatalf("Error. %s\r\n", err) //dbg
        }

        // Show Results
        fmt.Printf("[%d; %d] -> [%d].\r\n", args.A, args.B, result) //dbg
    }

再一次。这个golang程序运行正常。

但接下来我无法理解。

    telnet localhost 3000
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    {
    "jsonrpc":"2.0", 
    "method":"Arithmetic.Multiply", 
    "params": { "A": 5, "B": 6 },
    "id":1
    }
    {"id":1,"result":null,"error":"json: cannot unmarshal object into Go value of type [1]interface {}"}

请给我一些建议或出现这种错误的原因。原始请求有什么问题?

提前致谢!

1 个答案:

答案 0 :(得分:1)

您的代码似乎没问题。

但是在请求中,params应该是一个包含实际参数的数组。

尝试使用以下有效负载,它应该可以工作:

{ 
  "jsonrpc":"2.0",
  "method":"Arithmetic.Multiply", 
  "params": [ { "A": 5, "B": 6 } ], 
  "id":1 
} 

(注意“[”和“]”包含实际的参数)

相关问题