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
trueorfalse) -
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.