Reader
Reader is an incremental parser (also called a pull parser) that transforms the JSON input into a sequence of C++ tokens. This transformation is done piecemeal, which means that the reader will stay at the first token until explicitly instructed to parse the next token.
Based on the Iterator design pattern, reader parses just enough of the input to identify a single token.
The reader provides various accessors that can be used to examine or convert
the current token.
Reader member function |
Description |
|
Returns the current token. |
|
Returns the symbol of the current token. |
|
Returns the category of the current token. |
|
Returns the current level of nested containers. The levels starts with zero for the outmost level. |
|
Returns the current error code. |
|
Returns a view of the raw input of the current value.]] |
|
Returns the current value. The raw input is converted into the requested value type. |
No data is converted until explicitly requested with reader::value<T>().
Notice that the return type for reader::value<T>() must be specified as a
template parameter.
The return type can be a boolean, a number, or a string as described below.
The requested type must match the current token as returned by
reader::type(); otherwise a run-time error will be raised.
NOTE:
Requesting the value of an incompatible type will result in a run-time error. For example, attempting to read a string as an integer:
assert(reader.symbol() == json::symbol::string);
int number = reader.value<int>(); // Throws exception
|
Requesting an unsupported type will result in a compile-time error. For example, attempting to read a user-defined struct:
|
The unconverted textual data of the current token can be obtained with
reader::literal().
This can be useful when displaying errors.
The result of reader::literal() is different from reader::value<std::string>().
When you are done with the current token, the next token is found with
reader::next().
This function returns a bool, which is true unless either an error or the end of
the input was encountered.
Whitespaces and separators are skipped.
Errors in the input are identified with an error token, and the current error
can be obtained with reader::error().
Boolean
Boolean values are indicated by the json::symbol::boolean token. The value is
requested by reader::value<bool>().
std::string input = "true";
json::reader reader(input);
assert(reader.symbol() == json::symbol::boolean);
assert(reader.literal() == "true");
assert(reader.value<bool>());
Number
While JSON does not distinguish between integer and floating-point numbers, C++ does make this distinction and therefore Trial.Protocol does too. However, integers can be read as floating-point numbers, and floating-point numbers can be read as integers. NOTE: Reading a floating-point number as an integer will round the number, so it may result in loss of information.]
Numbers are identified as integers if the consists of digits only.
std::string input = "42";
json::reader reader(input);
assert(reader.symbol() == json::symbol::integer);
assert(reader.literal() == "42");
assert(reader.value<int>() == 42);
Numbers are detected as floating-point if they contain a decimal point or an exponent.
std::string input = "3.1415";
json::reader reader(input);
assert(reader.symbol() == json::symbol::number);
assert(reader.literal() == "3.1415");
assert(reader.value<double>() == 3.1415);
Integers can be read as floating-point numbers as well.
std::string input = "42";
json::reader reader(input);
assert(reader.symbol() == json::symbol::integer);
assert(reader.value<double>() == 42.0);
Floating-point numbers can also be read as integers. The number will be rounded to the nearest integer.
std::string input = "3.1415";
json::reader reader(input);
assert(reader.symbol() == json::symbol::number);
assert(reader.value<int>() == 3);
Any kind of additional constraints have to be enforced by the application layer. For instance, if we have a protocol with a size field, then logically this field cannot be negative or a fraction, even if JSON numbers allow this.
String
Strings are identified with the json::symbol::string token, and is converted
into a UTF-8 encoded string with reader::value<std::string>().
std::string input = "\"alpha\\n\"";
json::reader reader(input);
assert(reader.symbol() == json::symbol::string);
assert(reader.literal() == "\"alpha\\n\"");
assert(reader.value<std::string>() == "alpha\n");
Null
Null indicates the absence of a value, although it is encoded explicitly in the
JSON format as the null literal string.
std::string input = "null";
json::reader reader(input);
assert(reader.symbol() == json::symbol::null);
Array
Arrays are delimited by a begin-token and an end-token. Array members are comma separated. Arrays can contain any JSON type, including a nested array or a nested associative array.
std::string input = "[42]";
json::reader reader(input);
assert(reader.symbol() == json::symbol::begin_array);
reader.next();
assert(reader.symbol() == json::symbol::integer);
assert(reader.value<int>() == 42);
reader.next();
assert(reader.symbol() == json::symbol::end_array);