Coder Social home page Coder Social logo

jsonrpc-lean's Introduction

jsonrpc-lean

version: 1.1.0

An LGPL licensed, client/server, transport-agnostic, JSON-RPC library for C++.

The initial jsonrpc-lean implementation is derived from xsonrpc (https://github.com/erijo/xsonrpc) by Erik Johansson (https://github.com/erijo/). Many thanks to him.

The main idea behind branching xsonrpc and building a new project is to have a simple, transport-agnostic, header-only implementation, with as little external dependencies as possible.

Anyone can use this lib by just adding the include folder to their include path and they are good to go.

Currently, the only dependency is rapidjson (https://github.com/Tencent/rapidjson), which is also a header-only implementation. Add rapidjson to your include path, and done.

Another advantage of removing the dependencies is that now it is easy to compile and use on most platforms that support c++, without much work.

Examples

A simple server that process JSON-RPC requests:

#include "jsonrpc-lean/server.h"

class Math {
public:
	int Add(int a, int b) {
		return a + b;
	}

	int64_t AddArray(const jsonrpc::Value::Array& a) {
		return std::accumulate(a.begin(), a.end(), int64_t(0),
			[](const int64_t& a, const jsonrpc::Value& b) { return a + b.AsInteger32(); });
	};
};

std::string Concat(const std::string& a, const std::string& b) {
	return a + b;
}

jsonrpc::Value::Struct ToStruct(const jsonrpc::Value::Array& a) {
	jsonrpc::Value::Struct s;
	for (size_t i = 0; i < a.size(); ++i) {
		s[std::to_string(i)] = jsonrpc::Value(a[i]);
	}
	return s;
}

void PrintNotification(const std::string& a) {
    std::cout << "notification: " << a << std::endl;
}

int main() {
	Math math;
	jsonrpc::Server server;
	
	jsonrpc::JsonFormatHandler jsonFormatHandler;
	server.RegisterFormatHandler(jsonFormatHandler);

	auto& dispatcher = server.GetDispatcher();
	// if it is a member method, you must use this 3 parameter version, passing an instance of an object that implements it
	dispatcher.AddMethod("add", &Math::Add, math);
	dispatcher.AddMethod("add_array", &Math::AddArray, math); 
	
	// if it is just a regular function (non-member or static), you can you the 2 parameter AddMethod
	dispatcher.AddMethod("concat", &Concat);
	dispatcher.AddMethod("to_struct", &ToStruct);
	dispatcher.AddMethod("print_notification", &PrintNotification);

	// on a real world, these requests come from your own transport implementation (sockets, http, ipc, named-pipes, etc)
	const char addRequest[] = "{\"jsonrpc\":\"2.0\",\"method\":\"add\",\"id\":0,\"params\":[3,2]}";
	const char concatRequest[] = "{\"jsonrpc\":\"2.0\",\"method\":\"concat\",\"id\":1,\"params\":[\"Hello, \",\"World!\"]}";
	const char addArrayRequest[] = "{\"jsonrpc\":\"2.0\",\"method\":\"add_array\",\"id\":2,\"params\":[[1000,2147483647]]}";
	const char toStructRequest[] = "{\"jsonrpc\":\"2.0\",\"method\":\"to_struct\",\"id\":5,\"params\":[[12,\"foobar\",[12,\"foobar\"]]]}";
	const char printNotificationRequest[] = "{\"jsonrpc\":\"2.0\",\"method\":\"print_notification\",\"params\":[\"This is just a notification, no response expected!\"]}";

	std::shared_ptr<jsonrpc::FormattedData> outputFormattedData;
    std::cout << "request: " << addRequest << std::endl;
    outputFormattedData = server.HandleRequest(addRequest);
    std::cout << "response: " << outputFormattedData->GetData() << std::endl;

    outputFormattedData.reset();
    std::cout << "request: " << concatRequest << std::endl;
    outputFormattedData = server.HandleRequest(concatRequest);
    std::cout << "response: " << outputFormattedData->GetData() << std::endl;

    outputFormattedData.reset();
    std::cout << "request: " << addArrayRequest << std::endl;
    outputFormattedData = server.HandleRequest(addArrayRequest);
    std::cout << "response: " << outputFormattedData->GetData() << std::endl;

    outputFormattedData.reset();
    std::cout << "request: " << toStructRequest << std::endl;
    outputFormattedData = server.HandleRequest(toStructRequest);
    std::cout << "response: " << outputFormattedData->GetData() << std::endl;
	
	outputFormatedData.reset();
    std::cout << "request: " << printNotificationRequest << std::endl;
    outputFormatedData = server.HandleRequest(printNotificationRequest);
    std::cout << "response size: " << outputFormatedData->GetSize() << std::endl;

	return 0;
}

A client capable of generating requests for the server above could look like this:

#include "jsonrpc-lean/client.h"

int main(int argc, char** argv) {

	const char addResponse[] = "{\"jsonrpc\":\"2.0\",\"id\":0,\"result\":5}";
    const char concatResponse[] = "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":\"Hello, World!\"}";
    const char addArrayResponse[] = "{\"jsonrpc\":\"2.0\",\"id\":2,\"result\":2147484647}";
    const char toStructResponse[] = "{\"jsonrpc\":\"2.0\",\"id\":4,\"result\":{\"0\":12,\"1\":\"foobar\",\"2\":[12,\"foobar\"]}}";

    std::unique_ptr<jsonrpc::FormatHandler> formatHandler(new jsonrpc::JsonFormatHandler());
	jsonrpc::Client client(*formatHandler);

	std::shared_ptr<FormattedData> jsonRequest = client.BuildRequestData("add", 3, 2);
	std::cout << jsonRequest->GetData(); // this will output the json-rpc request string
	jsonrpc::Response parsedResponse = client.ParseResponse(addResponse);
    std::cout << "Parsed response: " << parsedResponse.GetResult().AsInteger32() << std::endl << std::endl;
	
	jsonRequest.reset(client.BuildRequestData("concat", "Hello, ", "World!"));
	std::cout << jsonRequest->GetData();
	parsedResponse = client.ParseResponse(concatResponse);
        std::cout << "Parsed response: " << parsedResponse.GetResult().AsString() << std::endl << std::endl;

	jsonrpc::Request::Parameters params;
	{
		jsonrpc::Value::Array a;
		a.emplace_back(1000);
		a.emplace_back(std::numeric_limits<int32_t>::max());
		params.push_back(std::move(a));
	}
	jsonRequest.reset(client.BuildRequestData("add_array", params));
	std::cout << jsonRequest->GetData(); 
	parsedResponse = client.ParseResponse(addArrayResponse);
    std::cout << "Parsed response: " << parsedResponse.GetResult().AsInteger64() << std::endl << std::endl;

	params.clear();
	{
		jsonrpc::Value::Array a;
		a.emplace_back(12);
		a.emplace_back("foobar");
		a.emplace_back(a);
		params.push_back(std::move(a));
	}
	jsonRequest.reset(client.BuildRequestData("to_struct", params));
	std::cout << jsonRequest->GetData(); 
	parsedResponse = client.ParseResponse(toStructResponse);
	auto structValue = parsedResponse.GetResult().AsStruct();
	std::cout << "Parsed response: " << std::endl;
	std::cout << "   0 : " << structValue["0"].AsInteger32() << std::endl;
	std::cout << "   1 : " << structValue["1"].AsString() << std::endl;
	std::cout << "   2 : [" << structValue["2"].AsArray()[0] << ", " << structValue["2"].AsArray()[1] << "]" << std::endl;
	
	jsonRequest.reset(client.BuildNotificationData("print_notification", "This is just a notification, no response expected!"));
	std::cout << jsonRequest->GetData();

    return 0;
}

Usage Requirements

To use jsonrpc-lean on your project, all you need is:

  • A C++ compiler (GCC 5.0+ (Linux), XCode/Clang (OSX 10.7+), MSVC 14.0+ (Visual Studio 2015))
  • rapidjson (Only need the include folder on your include path, don't worry about compiling it)

jsonrpc-lean's People

Contributors

bmod avatar uskr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

jsonrpc-lean's Issues

server settings

Hi

Im trying to use your jsonrpc implementation, thanks for making that!!
But i may be missing something, because i don't see anywhere how to set the server ip and port.......
How can i know which ip and port are the server running??¿¿¿

Thanks!!

Make a release

Hi! Thank you for the library!

Can you please make a release of the library? It helps a lot with packaging your libray into dependency managers like Conan.

For packaging we require version of a library. Without your help we cannot do it, unfortunately.

Thank you a lot!

Number string parameters get detected as date

When giving a number as text (e.g. "33") for a request parameter the JSON parser interprets it as a date type.

E.g. (see examples/testserver.cpp)

std::string Concat(const std::string& a, const std::string& b) {
	return a + b;
}
dispatcher.AddMethod("concat", &Concat);
const char request[] = R"({"jsonrpc":"2.0","method":"concat","id":1,"params":["Hello, ","33"]})";
server.HandleRequest(concatRequest);
// -> {"jsonrpc":"2.0","id":1,"error":{"code":-32602,"message":"Invalid parameters"}}

jsonrpc::util::ParseIso8601DateTime as called from JSON reader in Value GetValue(const rapidjson::Value&) returns true which is wrong. Live demo here.

I did not expect treatment for data strings since IMO it is not part of the JSON standard. I guess interpreting strings as data and serializing dates into strings, would better done in the application layer, or I'd rather pick a whole other data format like MessagePack.

I would not be sad if support for Value::Type::DATE_TIME is simply kicked out of jsonrpc-lean. 😑

uint32_t and uint64_t types

Is there a reason why uint32_t and uint64_t are omitted from Value type? I see they are being converted to int64_t and double receptively. The problem is I'm unable to 'AddMethod' following :

uint32_t foo() {}

Thank you,
J

'memset' not declared on Ubuntu

Nice library 🍰
When compiling with GCC C++14 flavour on Linux I had to make a small change in util.h in line 24

#include <string.h>

Apparently memset is part of <string.h> and not STL's <string>.
See also on Stackoverflow this answer:

You should use #include <string.h> in both C and C++, if you want to use ::memset. #include gets you std::memset, and if it also makes ::memset available, it does so by accident. The Standard permits it but does not require it to do so

Right now I have not time to compile on Mac and Windows, therefore I did not assemble a pull request though.

LGPL version 2.1 contradiction

Hello,
nice approach, but not really useful.

Since you advertise you library as header only, then I would suggest to change license LGPL v2.1 to LGPL v3.0. Because LGPL v2.1 requires to link library dynamically, which is problematic with headers only libraries and is solved in LGPL v3.0, as stated here:
http://eigen.tuxfamily.org/index.php?title=Licensing_FAQ&oldid=1117#But_doesn.27t_the_LGPL_have_issues_with_code_that_is_in_header_files.2C_and_template_libraries.3F

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.