Channels ▼
RSS

Web Development

JSON and the Microsoft C++ REST SDK


In the first installment in this two-part series on consuming REST services with the Microsoft C++ REST SDK, I explained how to start working with the SDK and the asynchronous features to connect to a REST service and execute a simple HTTP GET request. In this article, I explain how to retrieve and send JSON data, work with asynchronous streams, and the different HTTP methods usually required when interacting with REST services.

Working with JSON

In the previous article, I explained how to execute a simple HTTP GET request. Here, I work with a complex JSON response. I'll use a sample REST service based on the ASP.NET Web API introduced in .NET Framework 4.5 that I explained in Access Data with REST in Windows 8 Apps. This image shows an example of the JSON response produced by an HTTP GET that requests all the groups and their items to the REST service in the popular Fiddler Web debugger.

The following lines show the complete JSON response when you make an HTTP GET request to /api/groups. The response includes six groups. The first group whose Title is Cloud has two items. The other groups don't have items.

[
   {
      "Title":"Cloud",
      "Subtitle":"Cloud Developer",
      "Description":"Cloud feature articles",
      "MainPage":"cloud",
      "Items":[
         {
            "Title":"AMD's Bold ARM Server Gambit",
            "Subtitle":"AMD's Bold ARM Server Gambit",
            "Description":"By combining 64-bit ARM processors with server-side technology, the company that led the x86 architecture into the 64-bit world is hoping to reinvent the data center and give itself new life.",
            "Content":"Content for AMD's Bold ARM Server Gambit...",
            "MainPage":"cloud/amds-bold-arm-server-gambit/240012549",
            "Id":"240012549"
         },
         {
            "Title":"How Atlassian moved a code base of 21,000 files with more than 47,000 commits on its best-selling product from Subversion to Git without stopping the development workflow.",
            "Subtitle":"Migrating from Subversion to Git and the Lessons Learned",
            "Description":"It is incredible how the cloud growths",
            "Content":"Content for Migrating from Subversion to Git and the Lessons Learned...",
            "MainPage":"cloud/migrating-from-subversion-to-git-and-the/240009175",
            "Id":"120020304050"
         }
      ],
      "Id":"1"
   },
   {
      "Title":"Mobile",
      "Subtitle":"Mobile Developer",
      "Description":"Mobile feature articles",
      "MainPage":"mobile",
      "Items":null,
      "Id":"2"
   },
   {
      "Title":"Parallel",
      "Subtitle":"Parallel Programming",
      "Description":"Parallel feature articles",
      "MainPage":"parallel",
      "Items":null,
      "Id":"3"
   },
   {
      "Title":".NET",
      "Subtitle":"M-Dev",
      "Description":"The world of Microsoft Developers",
      "MainPage":"windows",
      "Items":null,
      "Id":"4"
   },
   {
      "Title":"JVM Languages",
      "Subtitle":"Powered by Java Virtual Machine",
      "Description":"The world of JVM languages",
      "MainPage":"jvm",
      "Items":null,
      "Id":"5"
   },
   {
      "Title":"C/C++",
      "Subtitle":"Powered by C/C++",
      "Description":"The world of C/++ developers",
      "MainPage":"cpp",
      "Items":null,
      "Id":"6"
   }
]

The C++ REST SDK uses a single class (web::json::value) to represent JSON values and provides the necessary helpers to assist in serialization. The following code shows an example of a Windows console application that uses the C++ REST SDK to make the HTTP GET call http://localhost:58957/api/groups, and extract the JSON response. Then, the code loops over each JSON element and displays their keys and values by using the helpers provided by the C++ REST SDK.

Before using the code, you need to follow the steps explained in the previous installment for your Visual Studio project and execute the ASP.NET Web API example. In addition, you need to replace http://localhost:58957 with the URI and port on which your REST service is running.

// The code includes the most frequently used includes necessary to work with C++ REST SDK
#include "cpprest/containerstream.h"
#include "cpprest/filestream.h"
#include "cpprest/http_client.h"
#include "cpprest/json.h"
#include "cpprest/producerconsumerstream.h"
#include <iostream>
#include <sstream>

using namespace ::pplx;
using namespace utility;
using namespace concurrency::streams;

using namespace web;
using namespace web::http;
using namespace web::http::client;
using namespace web::json;

void DisplayJSONValue(json::value v)
{
	if (!v.is_null())
	{
		// Loop over each element in the object
		for (auto iter = v.cbegin(); iter != v.cend(); ++iter)
		{
			// It is necessary to make sure that you get the value as const reference
			// in order to avoid copying the whole JSON value recursively (too expensive for nested objects)
			const json::value &key = iter->first;
			const json::value &value = iter->second;

			if (value.is_object() || value.is_array())
			{
				// We have an object with children or an array
				if ((!key.is_null()) && (key.is_string()))
				{
					std::wcout << L"Parent: " << key.as_string() << std::endl;
				}
				// Loop over each element in the object by calling DisplayJSONValue
				DisplayJSONValue(value);
				if ((!key.is_null()) && (key.is_string()))
				{
					std::wcout << L"End of Parent: " << key.as_string() << std::endl;
				}
			}
			else
			{
				// Always display the value as a string
				std::wcout << L"Key: " << key.as_string() << L", Value: " << value.to_string() << std::endl;
			}
		}
	}
}

pplx::task<void> HTTPGetAsync()
{
	// I want to make the following HTTP GET: http://localhost:58957/api/groups
	http_client client(U("http://localhost:58957/api/"));

	// Manually build up an HTTP request with a header that specifies the content type and the request URI
	http_request request(methods::GET);
	request.headers().set_content_type(L"application/json");
	request.set_request_uri(U("groups"));


	// Make an HTTP GET request and asynchronously process the response
	return client
		.request(request)
		// The following code executes when the response is available
		.then([](http_response response) -> pplx::task<json::value>
		{
			std::wostringstream stream;
			stream.str(std::wstring());
			stream << L"Content type: " << response.headers().content_type() << std::endl;
			stream << L"Content length: " << response.headers().content_length() << L"bytes" << std::endl;
			std::wcout << stream.str();

			// If the status is OK extract the body of the response into a JSON value
			if (response.status_code() == status_codes::OK)
			{
				return response.extract_json();
			}
			else
			{
				// return an empty JSON value
				return pplx::task_from_result(json::value());
			}
		// Continue when the JSON value is available
		}).then([](pplx::task<json::value> previousTask)
		{
			// Get the JSON value from the task and call the DisplayJSONValue method
			try
			{
				json::value const & value = previousTask.get();
				DisplayJSONValue(value);
			}
			catch (http_exception const & e)
			{
				std::wcout << e.what() << std::endl;
			}
		});
}

#ifdef _MS_WINDOWS
int wmain(int argc, wchar_t *args[])
#else
int main(int argc, char *args[])
#endif
{
	std::wcout << L"Calling HTTPGetAsync..." << std::endl;
	// In this case, I call wait. However, you won’t usually want to wait for the asynchronous operations
	HTTPGetAsync().wait();

	return 0;
}

The wmain method in Windows calls the HTTPGetAsync method, which returns a pplx::task<void> instance that represents an asynchronous operation. However, in this case, the HTTPGetAsync method includes many chained asynchronous operations.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 
Dr. Dobb's TV