p4-web
Working with JSON
JSON is a file format common on the web. The starter code includes json.hpp
, a library for working with JSON in C++. To use the library, place the following at the top of a .cpp file:
#include "json.hpp"
using nlohmann::json;
JSON format
The JSON format is a simple text-based standard for representing structured data. It consists of the following data types:
-
numbers, which can be integer or floating point
-
strings
-
booleans (either
true
orfalse
) -
null
, which represents an empty value -
arrays, which are delimited by square brackets in the JSON format
-
objects, which are collections of key-value pairs and are delimited by curly braces. The keys must be strings, but the values may be any data type, including arrays or other objects.
Constructing a JSON object
The json.hpp
library defines the json
type to represent a JSON
value. The documentation has an
example
of constructing a json
object in C++ code. We summarize the example
here. Suppose we wanted to construct the following JSON object:
{
"pi": 3.141,
"happy": true,
"name": "Niels",
"nothing": null,
"an_array": [1, 0, 2],
"an_object": {
"currency": "USD",
"value": 42.99
}
}
This object has the following key-value pairs:
-
the key
"pi"
has a value that is the number3.141
-
"happy"
has a value that is the booleantrue
-
"name"
has a value that is the string"Niels"
-
"nothing"
has a null (empty) value -
the value for
"an_array"
is an array of three elements -
the value for
"an_object"
is an object with two of its own key-value pairs
We can create the JSON object in C++ as follows:
json j2;
j2["pi"] = 3.141;
j2["happy"] = true;
j2["name"] = "Niels";
j2["nothing"] = json();
j2["an_array"] = {1, 0, 2};
j2["an_object"] = {
{"currency", "USD"},
{"value", 42.99}
};
The value for a particular key can be read using the same subscript syntax:
cout << j2["pi"] << endl; // prints 3.141
cout << j2["answer"] << endl; // prints {"everything":42}
j2["tau"] = 6.283; // inserts "tau":6.283 into j2
cout << j2["tau"] << endl; // prints 6.283
A JSON object can also be created with a C++ initializer list, as in:
j2["an_object"] = {
{"currency", "USD"},
{"value", 42.99}
};
Each element of the C++ initializer list must be another initializer list,
containing both a key and a value. In this example, the key
"currency"
is associated with the string "USD"
, and the key
"value"
is associated with the number 42.99
.
The following creates the same object as j2
above using initializer
lists:
json j2 = {
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{"an_array", {1, 0, 2}},
{"an_object", {
{"currency", "USD"},
{"value", 42.99}
}
}
};
JSON arrays
Build a JSON array using push_back()
.
json output;
json j4 = {
{"happy", true},
{"pi", 3.141}
};
output.push_back(j4);
json j5 = {
{"happy", true},
{"pi", 3.14159265359}
};
output.push_back(j5);
The resulting JSON is
[
{
"happy": true,
"pi": 3.141
},
{
"happy": true,
"pi": 3.14159265359
}
]
Reading JSON from a stream
JSON-formatted data can be read from a stream into a json
object using operator>>
:
json j3;
cin >> j3;
Writing JSON to a stream
A json
object can be inserted directly into a stream. However, it
does not get “pretty printed” with proper indentation. Instead, use
the dump()
member function to convert a json
object into a string
and then insert the string into a stream:
json j4 = {
{"happy", true},
{"pi", 3.141}
};
string str2 = j4.dump(4) + "\n"; // dump with indentation using 4 spaces
cout << str2; // print the dumped string
This results in the following:
{
"happy": true,
"pi": 3.141
}
The key-value pairs are ordered alphabetically by key.
Compute the content length for a request or response from the length of the dumped string.
size_t content_length = str2.length();
Pitfall: the string should include a trailing newline before computing the length.