json_rpc_2 2.1.0

  • Readme
  • Changelog
  • Installing
  • 89

A library that implements the JSON-RPC 2.0 spec.

Server #

A JSON-RPC 2.0 server exposes a set of methods that can be called by clients. These methods can be registered using Server.registerMethod:

import "package:json_rpc_2/json_rpc_2.dart" as json_rpc;
import "package:stream_channel/stream_channel.dart";
import "package:web_socket_channel/io.dart";

main() async {
  var socket = IOWebSocketChannel.connect('ws://localhost:4321');

  // The socket is a StreamChannel<dynamic> because it might emit binary
  // List<int>s, but JSON RPC 2 only works with Strings so we assert it only
  // emits those by casting it.
  var server = new json_rpc.Server(socket.cast<String>());

  // Any string may be used as a method name. JSON-RPC 2.0 methods are
  // case-sensitive.
  var i = 0;
  server.registerMethod("count", () {
    // Just return the value to be sent as a response to the client. This can
    // be anything JSON-serializable, or a Future that completes to something
    // JSON-serializable.
    return i++;

  // Methods can take parameters. They're presented as a [Parameters] object
  // which makes it easy to validate that the expected parameters exist.
  server.registerMethod("echo", (params) {
    // If the request doesn't have a "message" parameter, this will
    // automatically send a response notifying the client that the request
    // was invalid.
    return params.getNamed("message");

  // [Parameters] has methods for verifying argument types.
  server.registerMethod("subtract", (params) {
    // If "minuend" or "subtrahend" aren't numbers, this will reject the
    // request.
    return params.getNum("minuend") - params.getNum("subtrahend");

  // [Parameters] also supports optional arguments.
  server.registerMethod("sort", (params) {
    var list = params.getList("list");
    if (params.getBool("descending", orElse: () => false)) {
      return params.list.reversed;
    } else {
      return params.list;

  // A method can send an error response by throwing a
  // `json_rpc.RpcException`. Any positive number may be used as an
  // application- defined error code.
  const DIVIDE_BY_ZERO = 1;
  server.registerMethod("divide", (params) {
    var divisor = params.getNum("divisor");
    if (divisor == 0) {
      throw new json_rpc.RpcException(
          DIVIDE_BY_ZERO, "Cannot divide by zero.");

    return params.getNum("dividend") / divisor;

  // To give you time to register all your methods, the server won't actually
  // start listening for requests until you call `listen`.

Client #

A JSON-RPC 2.0 client calls methods on a server and handles the server's responses to those method calls. These methods can be called using Client.sendRequest:

import "package:json_rpc_2/json_rpc_2.dart" as json_rpc;
import "package:stream_channel/stream_channel.dart";
import "package:web_socket_channel/html.dart";

main() async {
  var socket = HtmlWebSocketChannel.connect('ws://localhost:4321');
  var client = new json_rpc.Client(socket);

  // This calls the "count" method on the server. A Future is returned that
  // will complete to the value contained in the server's response.
  client.sendRequest("count").then((result) => print("Count is $result."));

  // Parameters are passed as a simple Map or, for positional parameters, an
  // Iterable. Make sure they're JSON-serializable!
  client.sendRequest("echo", {"message": "hello"})
      .then((echo) => print('Echo says "$echo"!'));

  // A notification is a way to call a method that tells the server that no
  // result is expected. Its return type is `void`; even if it causes an
  // error, you won't hear back.

  // If the server sends an error response, the returned Future will complete
  // with an RpcException. You can catch this error and inspect its error
  // code, message, and any data that the server sent along with it.
  client.sendRequest("divide", {"dividend": 2, "divisor": 0})
      .catchError((error) {
    print("RPC error ${error.code}: ${error.message}");

  // The client won't subscribe to the input stream until you call `listen`.

Peer #

Although JSON-RPC 2.0 only explicitly describes clients and servers, it also mentions that two-way communication can be supported by making each endpoint both a client and a server. This package supports this directly using the Peer class, which implements both Client and Server. It supports the same methods as those classes, and automatically makes sure that every message from the other endpoint is routed and handled correctly.

2.1.0 #

  • Server and related classes can now take an onUnhandledError callback to notify callers of unhandled exceptions.

2.0.10 #

  • Allow stream_channel version 2.x

2.0.8 #

  • Updated SDK version to 2.0.0-dev.17.0

2.0.7 #

  • When a Client is closed before a request completes, the error sent to that request's Future now includes the request method to aid in debugging.

2.0.6 #

  • Internal changes only.

2.0.5 #

  • Internal changes only.

2.0.4 #

  • Client.sendRequest() now throws a StateError if the client is closed while the request is in-flight. This avoids dangling Futures that will never be completed.

  • Both Client.sendRequest() and Client.sendNotification() now throw StateErrors if they're called after the client is closed.

2.0.3 #

  • Fix new strong-mode warnings.

2.0.2 #

  • Fix all strong-mode warnings.

2.0.1 #

  • Fix a race condition in which a StateError could be top-leveled if Peer.close() was called before the underlying channel closed.

2.0.0 #

  • Breaking change: all constructors now take a StreamChannel rather than a Stream/StreamSink pair.

  • Client.sendRequest() and Client.sendNotification() no longer throw StateErrors after the connection has been closed but before Client.close() has been called.

  • The various close() methods may now be called before their corresponding listen() methods.

  • The various close() methods now wait on the result of closing the underlying StreamSink. Be aware that in some circumstances StreamControllers' Sink.close() futures may never complete.

1.2.0 #

  • Add Client.isClosed and Server.isClosed, which make it possible to synchronously determine whether the connection is open. In particular, this makes it possible to reliably tell whether it's safe to call Client.sendRequest.

  • Fix a race condition in Server where a StateError could be thrown if the connection was closed in the middle of handling a request.

  • Improve stack traces for error responses.

1.1.1 #

  • Update the README to match the current API.

1.1.0 #

  • Add a done getter to Client, Server, and Peer.

1.0.0 #

  • Add a Client class for communicating with external JSON-RPC 2.0 servers.

  • Add a Peer class that's both a Client and a Server.

0.1.0 #

  • Remove Server.handleRequest() and Server.parseRequest(). Instead, new Server() takes a Stream and a StreamSink and uses those behind-the-scenes for its communication.

  • Add Server.listen(), which causes the server to begin listening to the underlying request stream.

  • Add Server.close(), which closes the underlying request stream and response sink.

0.0.2+3 #

  • Widen the version constraint for stack_trace.

0.0.2+2 #

  • Fix error response to include data from RpcException when not a map.

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  json_rpc_2: ^2.1.0

2. Install it

You can install packages from the command line:

with pub:

$ pub get

with Flutter:

$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:json_rpc_2/json_rpc_2.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on Apr 4, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6

Health suggestions

Fix lib/src/server.dart. (-9.08 points)

Analysis of lib/src/server.dart reported 19 hints, including:

line 35 col 20: Unnecessary new keyword.

line 41 col 22: Unnecessary new keyword.

line 88 col 20: Unnecessary new keyword.

line 115 col 13: Unnecessary new keyword.

line 147 col 20: Unnecessary new keyword.

Fix lib/src/parameters.dart. (-5.36 points)

Analysis of lib/src/parameters.dart reported 11 hints, including:

line 51 col 16: Unnecessary new keyword.

line 53 col 16: Unnecessary new keyword.

line 58 col 16: Unnecessary new keyword.

line 60 col 16: Unnecessary new keyword.

line 63 col 13: Unnecessary new keyword.

Fix lib/src/client.dart. (-4.41 points)

Analysis of lib/src/client.dart reported 9 hints, including:

line 31 col 28: Unnecessary new keyword.

line 64 col 20: Unnecessary new keyword.

line 68 col 13: Unnecessary new keyword.

line 109 col 21: Unnecessary new keyword.

line 110 col 28: Unnecessary new keyword.

Fix additional 4 files with analysis or formatting issues. (-7.43 points)

Additional issues in the following files:

  • lib/src/peer.dart (7 hints)
  • lib/src/utils.dart (5 hints)
  • lib/src/channel_manager.dart (2 hints)
  • lib/src/exception.dart (1 hint)

Maintenance suggestions

Maintain an example. (-10 points)

Create a short demo in the example/ directory to show how to use this package.

Common filename patterns include main.dart, example.dart, and json_rpc_2.dart. Packages with multiple examples should provide example/README.md.

For more information see the pub package layout conventions.


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.0.0 <3.0.0
stack_trace ^1.0.0 1.9.3
stream_channel >=1.1.0 <3.0.0 2.0.0
Transitive dependencies
async 2.4.1
collection 1.14.12
path 1.6.4
Dev dependencies
test ^1.0.0