JSON [de]serialization for protobuf + embedded HTTP server and client in C++.
pjcore is a well-tested cross-platform library in C++ for handling JSON, Protocol Buffers (protobuf) and HTTP that
- Implements a JSON parser with optional support for trailing commas, comments, signed and unsigned 64-bit integers, NaN and Infinity values,
- Implements a JSON printer with optional support for pretty-print,
- Implements functions for inline JSON construction, so that
MakeJsonObject("alpha", 3, "beta", MakeJsonArray(true, 7.5))
results in {"alpha": 3, "beta": [true, 7.5]}, - Establishes a natural mapping of protobuf message types to JSON, where messages are mapped to objects and repeated fields - to arrays,
- Implements serialization of protobuf messages to JSON format,
- Implements deserialization (parsing) of JSON format into protobuf messages, with support for safe type conversions like int to double and string with decimal value - to int,
- Defines HttpRequest and HttpResponse protobuf messages, encapsulating the most common cases of HTTP requests and responses, respectively,
- Implements an HTTP client that for a given HttpRequest with some URL fetches HttpResponse for that URL,
- Implements an HTTP server that listens to some port and handles requests from connecting clients by invoking your handler that takes HttpRequest and returns HttpResponse,
- Uses loose coupling and eschews singletons so that you can instantiate and use any number of HTTP clients and servers, and when you're done, they can be destroyed without leaking memory, connections or other resources,
- Uses libuv event loop mechanism for HTTP I/O, so that it can be used together with other libuv-based libraries.
After you've cloned the project with
git clone https://github.com/protojson/pjcore.git
be sure to check out the external submodules with
git submodule init
git submodule update
Then on Linux or Mac run
./build.sh
or on Windows run
build.bat
to build the dependencies, library, unit tests and use cases.
message Business {
optional string name = 1;
optional string url = 2;
}
Business bookstore;
bookstore.set_name("The Shop Around The Corner");
bookstore.set_url("http://bookstore.com");
std::cout << pjcore::WriteJson(bookstore) << std::endl;
results in
{"name":"The Shop Around The Corner","url":"http:\/\/bookstore.com"}
std::cout << pjcore::WritePrettyJson(bookstore) << std::endl;
results in
{
"name": "The Shop Around The Corner",
"url": "http:\/\/bookstore.com"
}
message Article {
optional string title = 1;
optional string content = 2;
}
pjcore::Error error;
pjcore::JsonValue json;
if (!pjcore::ReadJson("{\"title\":\"Lorem Ipsum\","
"\"content\":\"Dolor sit amet.\"}",
&json, &error)) {
// error
} else {
Article article;
if (!pjcore::UnboxJsonValue(json, &article, &error)) {
// error
} else {
std::cout << article.DebugString() << std::endl;
}
}
results in
title: "Lorem Ipsum"
content: "Dolor sit amet."
message Review {
optional string reviewer = 1;
optional double rating = 2;
repeated pjcore.JsonValue.Property object_properties = 3;
}
pjcore::Error error;
pjcore::JsonValue json;
if (!pjcore::ReadJson("{\"reviewer\":\"Vegeta\","
"\"rating\":9001,"
"\"summary\":\"It's over nine thousand!\"}",
&json, &error)) {
// error
} else {
Review review;
if (!pjcore::UnboxJsonValue(json, &review, &error)) {
// error
} else {
std::cout << review.DebugString() << std::endl;
}
}
results in
reviewer: "Vegeta"
rating: 9001
object_properties {
name: "summary"
value {
type: TYPE_STRING
string_value: "It\'s over nine thousand!"
}
}
bool g_client_destroyed = false;
void OnClientDestroy() {
g_client_destroyed = true;
}
scoped_ptr<HttpResponse> g_response;
Error g_error;
void OnResponse(scoped_ptr<HttpResponse> response,
const Error& error) {
g_response = response.Pass();
g_error = error;
}
Error error;
SharedHttpHandler client = HttpClient::Create(
HttpClientConfig(), Bind(&OnClientDestroy), &error);
if (!client) {
// error
} else {
scoped_ptr<HttpRequest> request(new HttpRequest());
request->set_url("http://status.aws.amazon.com/rss/ec2-us-west-1.rss");
client->AsyncHandle(request.Pass(), Bind(&OnResponse));
client = NULL;
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
if (!g_response) {
// error
} else {
std::cout << g_response->content() << std::endl;
}
}
results in
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>Amazon Elastic Compute Cloud (N. California) Service Status</title>
<link>http://status.aws.amazon.com/</link>
...
</channel>
</rss>
class HelloWorldHttpHandler : public AbstractHttpHandler {
public:
HelloWorldHttpHandler()
: AbstractHttpHandler("HelloWorldHttpHandler", NULL) {}
void AsyncHandle(scoped_ptr<HttpRequest> request,
const HttpResponseCallback& on_response) {
scoped_ptr<HttpResponse> response(
new HttpResponse());
response->set_content("Hello, world!\n");
on_response.Run(response.Pass(), Error());
}
protected:
scoped_ptr<google::protobuf::Message> CaptureLive() const {
return scoped_ptr<google::protobuf::Message>();
}
};
bool g_server_destroyed = false;
void OnServerDestroy() {
g_server_destroyed = true;
}
HttpServerConfig config;
config.set_port(8080);
SharedHttpHandler handler(new HelloWorldHttpHandler());
Error error;
SharedHttpServer server = HttpServer::Create(
config, handler, &error);
if (!server) {
// error
} else if (!server->InitAsync(Bind(&OnServerDestroy), &error)) {
// error
server = NULL;
while (!g_server_destroyed) {
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}
} else {
for (;;) {
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}
}
> curl http://localhost:8080/
results in
Hello, world!
Unless otherwise stated, the copyright of all pjcore content belongs to the owners of http://protojson.com and is licensed under GNU General Public License, version 2. Feel free to contact us if you would like to consider a different license agreement for pjcore that would simplify its proprietary/commercial use.
Below is the list of pjcore dependencies with the details of their usage by pjcore, license type and copyright information.
Protocol Buffers (protobuf) are language-neutral, platform-neutral, extensible mechanism for serializing structured data.
Usage: pjcore library links against protobuf library, also includes code generated by protobuf compiler for structured data.
License: [BSD 3-clause](https://github.com/google/protobuf/blob/master/LICENSE)
Copyright: Google Inc.
Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all Internet users to experience the web.
Usage: pjcore library includes parts of it for callbacks, reference-counted and scoped pointers, lightweight strings and atomic operations.
License: [BSD 3-clause](http://src.chromium.org/viewvc/chrome/trunk/src/LICENSE)
Copyright: The Chromium Authors
Dynamic Annotations is a source code annotation that affects the generated code.
Usage: pjcore library includes it as a dependency for the used subset of Chromium.
License: [BSD 2-clause](https://chromium.googlesource.com/chromium/src/base/+/master/third_party/dynamic_annotations/LICENSE)
Copyright: Google Inc.
Google Test is a framework for writing C++ tests based on the xUnit architecture.
Usage: pjcore unit tests link against it, and also pjcore library includes parts of it for approximate floating-point number comparison.
License: [BSD 3-clause](http://opensource.org/licenses/BSD-3-Clause)
Copyright: Google Inc.
Google Mock is a library for writing and using C++ mock classes.
Usage: pjcore unit tests link against it it.
License: [BSD 3-clause](http://opensource.org/licenses/BSD-3-Clause)
Copyright: Google Inc.
Valgrind is an instrumentation framework for building dynamic analysis tools.
Usage: pjcore library includes parts of it that are a dependency for the used subset of Chromium.
License: [BSD-style license](https://chromium.googlesource.com/chromium/src/base/+/master/third_party/valgrind/LICENSE)
Copyright: Julian Seward
libuv is a multi-platform support library with a focus on asynchronous I/O.
Usage: pjcore library links against it for asynchronous I/O operations.
License: [Node's license](https://github.com/libuv/libuv/blob/master/LICENSE)
Copyright: Joyent, Inc. and other Node contributors
http-parser is a parser for HTTP messages written in C that parses both requests and responses.
Usage: pjcore library links against it for parsing HTTP requests and responses, and also pjcore unit tests include parts of it for testing its own HTTP and URL parsing.
License: [MIT](https://github.com/libuv/libuv/blob/master/LICENSE)
Copyright: Igor Sysoev, Joyent, Inc. and other Node contributors
cpplint is a lint-like tool for C++ source code.
Usage: cpplint can optionally be used when building pjcore source code to identify style issues.
License: [BSD 3-clause](http://google-styleguide.googlecode.com/svn/trunk/cpplint/README)
Copyright: Google Inc.
GYP is a build automation tool that generates native Visual Studio, Xcode and SCons and/or make build files from a platform-independent input format.
Usage: GYP is used for building pjcore dependencies, library, unit tests and tools.
License: [BSD 3-clause](https://code.google.com/p/gyp/source/browse/trunk/LICENSE)
Copyright: Google Inc.