dongsu3138 2017-07-03 18:50
浏览 139
已采纳

JSON-RPC,“无法解组对象”

I am trying to learn how JSON-RPC works and am testing it in Go language (golang). The Go program works fine. It does what it should do. But when I try to make a raw request via telnet, it gives an error.

The working and super simple JSON-RPC server is described here:

    // 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
", 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
", srv_addr, err) //dbg
        }
        log.Printf("Started RPC Handler at %s.
", 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
", err) //dbg
        }
    }

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

The working and super simple JSON-RPC client's code is following:

    // 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
", 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
", err) //dbg
        }

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

Once again. This golang program works fine.

But the next thing I cannot understand.

    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 {}"}

Please, give me some advice or the reason for such an error. What is wrong in the raw request?

Thanks in advance!

  • 写回答

1条回答 默认 最新

  • douluhaikao93943 2017-07-03 19:16
    关注

    Your code seems fine.

    But in the request, params is expected to be an array containing the actual parameters.

    Try with the following payload and it should work:

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

    (Note the "[" and "]" enclosing the actual param)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?