GitHub JSON API example ======================= Overview -------- This example implements a GitHub JSON API client in C. For more information about the use of JSON in gSOAP, see the [JSON documentation.](../../doc/xml-rpc-json/html/index.html) Implementing the client application ----------------------------------- The client application [`git.c`](git.c) is run at the command line and takes the URL of a repo and optional username and password as the command-line arguments to display the GitHub repo in JSON: #include "json.h" int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "Usage: git URL [username password]\nFor example: git https://api.github.com/orgs/Genivia/repos\n\n"); exit(0); } else { struct soap *ctx = soap_new1(SOAP_C_UTFSTRING | SOAP_XML_INDENT); struct value response; ctx->send_timeout = 10; /* 10 sec, stop if server is not accepting msg */ ctx->recv_timeout = 10; /* 10 sec, stop if server does not respond in time */ if (argc > 3) { /* Basic authentication with username password */ if (strncmp(argv[1], "https", 5)) { fprintf(stderr, "Basic authentication over http is not secure: use https\n"); exit(1); } ctx->userid = argv[2]; ctx->passwd = argv[3]; } if (json_call(ctx, argv[1], NULL, &response)) soap_print_fault(ctx, stderr); else json_write(ctx, &response); printf("\n\nOK\n"); soap_end(ctx); soap_free(ctx); } return 0; } /* Don't need a namespace table. We put an empty one here to avoid link errors */ struct Namespace namespaces[] = { {NULL, NULL} }; The C++ implementation [`git.cpp`](git.cpp) is very similar. However, in general, working with JSON data in C++ is a lot easier. The context `ctx` is initialized with `SOAP_C_UTFSTRING` to ensure 8-bit strings contain Unicode in UTF-8 format. The `SOAP_XML_INDENT` flag is optional, it displays JSON with an indented layout (just as XML is indented with this flag). The `struct value` data represents a JSON value (and in fact also an XML-RPC value). The GitHub API is called with `json_call(ctx, "URL", NULL, &response)` using an HTTP GET because the input parameter is NULL. The response JSON value is displayed with `json_write(ctx, &response)`. The call `json_call(ctx, "URL", in, out))` with pointers `in` and `out` to JSON values supports HTTP POST (both `in` and `out` are non-NULL), HTTP GET (`in` is NULL, `out` is non-NULL), HTTP PUT (`in` is non-NULL, `out` is NULL), and HTTP DELETE (`in` and `out` are NULL). JSON values can be read with `json_read(ctx, v)` with pointer `v` to an (empty) JSON value that will be assigned. To read from a file descriptor, set the context `ctx->recvfd` to the descriptor. To read from a string, set the context `ctx->is` to a `char*` string which works in C only. In C++ set the context `ctx->is` input stream to a string stream. JSON values can be written with `json_write(ctx, v)` with pointer `v` to a JSON value that will be saved. To write to a file descriptor, set the context `ctx->sendfd` to the descriptor. To write to a string, set the context `ctx->os` to point to a `char*` to be assigned with the string saved, which works in C only. In C++ set the context `ctx->os` output stream to a string stream. See the [JSON documentation](../../doc/xml-rpc-json/html/index.html) for more details on the JSON functions to create, inspect, and retrieve values. Authentication credentials are set with the context `ctx->userid` and `ctx->password` strings. For more information about authentication and HTTPS, see the [tutorials.](../../tutorials.html) Also see the [tutorials](../../tutorials.html) on how to set timeouts and handle signals. [![To top](../../images/go-up.png) To top](#) Build steps for the client application -------------------------------------- The use of JSON requires a one-time step to generate a data model that supports both JSON and the older XML-RPC protocols: [command] soapcpp2 -c -CSL xml-rpc.h The `xml-rpc.h` file and all other source code files that we need can be found in the `samples/xml-rpc-json` directory of the gSOAP package. To build the example client application we need `stdsoap2.h`, `stdsoap2.c`, `json.h`, `json.c`, `xml-rpc.c` and the generated `soapStub.h`, `soapH.h`, and `soapC.c` files: [command] cc -DWITH_OPENSSL -DWITH_GZIP -o git git.c xml-rpc.c json.c \ stdsoap2.c soapC.c -lcrypto -lssl -lz This may look odd, to include "soap-related" files in the build steps, but this is with a reason. We can combine JSON with all of our XML/SOAP Web services by simply adding an `#import "xml-rpc.h"` to the header file for soapcpp2 to process. The `xml-rpc.h` file specifies the data model to support JSON and XML-RPC. When combining XML/SOAP with JSON, we compile the `json.c` and `xml-rpc.c` files also, as shown. OpenSSL and Zlib are required for our client application to work propertly with HTTPS. [![To top](../../images/go-up.png) To top](#) Running the example ------------------- [command] ./git https://api.github.com/orgs/Genivia/repos This displays the Genivia public repos. [![To top](../../images/go-up.png) To top](#)