Channels ▼
RSS

Tools

JSON and the Microsoft C++ REST SDK


First, the HTTPGetAsync method creates a new instance of the web::http::client:http_client class to maintain a connection with the REST API whose base URI is http://localhost:58957/api/. Then, the method manually builds up an HTTP GET request with a header that specifies the content type (application/json) and sets the request URI to groups. This way, the HTTP GET request will be made to http://localhost:58957/api/groups.

  http_request request(methods::GET);
  request.headers().set_content_type(L"application/json");
  request.set_request_uri(U("groups"));

The following lines show the initial code that makes the request and return the resulting task instance that represents the asynchronous operation. The request method uses the previously built http_request instance (request) as an argument. Notice that the then method adds a continuation task to the task that executes the request. This task receives an http_response instance (response) and returns a pplx::task<json::value>, i.e., a task that will return a json::value.

  return client
                    .request(request)
                    .then([](http_response response) -> pplx::task<json::value>
                    {
  ...

After the request is processed, the code after the then continuation will be executed in a new task. If the status code of the response is OK, the code returns the result of the response.extract_json() method. This method extracts the body of the response message into a JSON value, checking that the content type is application/json. The method does the extraction in a new task and returns a pplx::task<json::value> instance.

There is another then method that adds a continuation task to the one that analyzes the response. This task receives a pplx::task<json::value> instance (previousTask) and starts executing when the JSON value is available. The code calls the previousTask.get method to retrieve the json::value extracted from the body of the response and uses it as an argument to call the DisplayJSONValue method.

}).then([](pplx::task<json::value> previousTask)
{
	try
	{
		json::value const & value = previousTask.get();
		DisplayJSONValue(value);
	}
	catch (http_exception const & e)
	{
		std::wcout << e.what() << std::endl;
	}
});

The JSON response includes nested objects, so the DisplayJSONValue method is prepared to deal with them. First, the method checks whether the received json::value (v) is null or not. Then, the code uses the cbegin and cend methods combined with the for statement to loop over each element in the object. The cbegin method gets the beginning const iterator element for a composite JSON value and the cend method gets the end const iterator element.

  for (auto iter = v.cbegin(); iter != v.cend(); ++iter)

The code within the for loop makes sure that it gets the values as const references in order to avoid copying the whole JSON value recursively, a situation that would be too expensive for nested objects. The code retrieves the first stored value (key) and the second stored value (value) for each element.

  const json::value &key = iter->first;
  const json::value &value = iter->second;

Then, the code checks whether the retrieved value is either an object (value.is_object() returns true) or an array (value.is_array() returns true). If this condition evaluates to true, the value is an object with children or an array, and therefore, the code displays the key as a string to indicate the parent's element name that will be listed when the key isn't null. Then, the code must loop over each element in the object or array, and therefore, it just calls the DisplayJSONValue method with the retrieved value as an argument. This way, with just a few lines of code, the different chained asynchronous methods analyze the response, extract the body of the response into a JSON value and iterate over the different nested JSON elements to display their keys and values. When the value isn't either an object or an array, the code displays both the key and the value as strings. The JSON response used in the example is a bit complex in order to represent a real-life JSON response and not just a few simple values without nested objects. In fact, arrays and nested objects make things a bit more complicated and the example demonstrates that you can easily work with them with the different methods in json::value.

if (value.is_object() || value.is_array())
{
	if ((!key.is_null()) && (key.is_string()))
	{
		std::wcout << L"Parent: " << key.as_string() << std::endl;
	}
	DisplayJSONValue(value);
	if ((!key.is_null()) && (key.is_string()))
	{
		std::wcout << L"End of Parent: " << key.as_string() << std::endl;
	}
}
else
{
	std::wcout << L"Key: " << key.as_string() << L", Value: " << value.to_string() << std::endl;
}

The following lines show the results displayed in the console after executing the code with the previously shown JSON response.

Calling HTTPGetAsync...
Content type: application/json; charset=utf-8
Content length: 1715bytes
Key: Title, Value: "Cloud"
Key: Subtitle, Value: "Cloud Developer"
Key: Description, Value: "Cloud feature articles"
Key: MainPage, Value: "cloud"
Parent: Items
Key: Title, Value: "AMD's Bold ARM Server Gambit"
Key: Subtitle, Value: "AMD's Bold ARM Server Gambit"
Key: Description, Value: "By combining 64-bit ARM processors with server-side te
chnology, the company that led the x86 architecture into the 64-bit world is hop
ing to reinvent the data center and give itself new life."
Key: Content, Value: "Content for AMD's Bold ARM Server Gambit..."
Key: MainPage, Value: "cloud/amds-bold-arm-server-gambit/240012549"
Key: Id, Value: "240012549"
Key: Title, Value: "How Atlassian moved a code base of 21,000 files with more th
an 47,000 commits on its best-selling product from Subversion to Git without sto
pping the development workflow."
Key: Subtitle, Value: "Migrating from Subversion to Git and the Lessons Learned"

Key: Description, Value: "It is incredible how the cloud growths"
Key: Content, Value: "Content for Migrating from Subversion to Git and the Lesso
ns Learned..."
Key: MainPage, Value: "cloud/migrating-from-subversion-to-git-and-the/240009175"

Key: Id, Value: "120020304050"
End of Parent: Items
Key: Id, Value: "1"
Key: Title, Value: "Mobile"
Key: Subtitle, Value: "Mobile Developer"
Key: Description, Value: "Mobile feature articles"
Key: MainPage, Value: "mobile"
Key: Items, Value: null
Key: Id, Value: "2"
Key: Title, Value: "Parallel"
Key: Subtitle, Value: "Parallel Programming"
Key: Description, Value: "Parallel feature articles"
Key: MainPage, Value: "parallel"
Key: Items, Value: null
Key: Id, Value: "3"
Key: Title, Value: ".NET"
Key: Subtitle, Value: "M-Dev"
Key: Description, Value: "The world of Microsoft Developers"
Key: MainPage, Value: "windows"
Key: Items, Value: null
Key: Id, Value: "4"
Key: Title, Value: "JVM Languages"
Key: Subtitle, Value: "Powered by Java Virtual Machine"
Key: Description, Value: "The world of JVM languages"
Key: MainPage, Value: "jvm"
Key: Items, Value: null
Key: Id, Value: "5"
Key: Title, Value: "C/C++"
Key: Subtitle, Value: "Powered by C/C++"
Key: Description, Value: "The world of C/++ developers"
Key: MainPage, Value: "cpp"
Key: Items, Value: null
Key: Id, Value: "6" 

As you work with many chained asynchronous tasks, you might be wondering about the difficulties when debugging the different pieces of code that execute on diverse tasks. The debugging features available in Visual Studio 2012 didn't provide all the necessary information for developers to understand the state of asynchronous code execution nor easily find and fix the asynchronous code. However, Visual Studio 2013 introduced async-aware debugging and made many changes to the different debugging windows that developers were accustomed to watching in Visual Studio 2012.

Visual Studio 2013 makes it easier for you to debug the asynchronous code that you usually write when working with C++ REST SDK. Figure 1 shows the enhanced Call Stack window in Visual Studio 2013 that displays allows you to know how you arrived to the actual line within the DisplayJSONValue. If you want to dive deeper on the new Visual Studio 2013 async-aware debugging features, you can read Visual Studio 2013 Asynchronous Debugging. That article is in C#, but you can use the same features in your C++ code with the asynchronous calls generated with the C++ REST SDK.

[Click image to view at full size]

Figure 1: The enhanced Call Stack window in Visual Studio 2013 displaying an additional frame that adds information about an asynchronous call.

Creating JSON Objects

Creating JSON objects with the C++ REST SDK is not as easy as it is with JavaScript, however, the boilerplate is significantly reduced in C++. The following lines show a sample CreateAndDisplayJSONObject method that creates a JSON object with many keys and values that were part of the sample JSON response.

void CreateAndDisplayJSONObject()
{
	// Create a JSON object.
	json::value obj;
	obj[L"Title"] = json::value::string(U("Mobile"));
	obj[L"Subtitle"] = json::value::string(U("Mobile Developer"));
	obj[L"Description"] = json::value::string(U("Mobile feature articles"));
	obj[L"MainPage"] = json::value::string(U("mobile"));
	obj[L"Items"] = json::value::null();
	obj[L"Id"] = json::value::string(U("2"));

	// Write the current JSON value to a stream with the native platform character width
	utility::stringstream_t stream;
	obj.serialize(stream);

	// Display the string stream
	std::wcout << stream.str();
}


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.
 

Video