Yson provides classes for reading and writing JSON and UBJSON files, and is particularly well suited for serialization/de-serialization and processing very large JSON files. The library has two main interfaces: Reader implemented by JsonReader and UBJsonReader, and Writer, implemented by JsonWriter and UBJsonWriter. Reader is somewhat inspired by .Net's XmlReader and makes it easy to iterate through the contents of JSON and UBJSON files. Writer is similarly inspired by .Net's XmlWriter and writes JSON and UBJSON contents directly to a stream or file.
- Reads files, streams and memory buffers.
- Supports all standard text encodings (UTF-8, UTF-16, even UTF-32).
- Supports most of JSON5 extension to the basic JSON syntax, including JavaScript comments and strings spanning multiple lines.
- Memory-efficient and fairly fast when processing large files.
- Released under the 2-clause BSD Licence.
- its two constructors, one taking in a std::istream, the other the name of a file.
- nextKey() for advancing to the next key in a JSON-object.
- nextValue() for advancing to the next value in a JSON-array or JSON-object.
- enter() for entering the JSON-array or JSON-object starting at the current position in the file. nextKey() and nextValue() will only advance through the most recently entered structure, structures that haven been entered will be skipped entirely by next time either of the two functions is called.
- leave() for leaving the most recently entered JSON-array or JSON-object.
- read(...) for reading the current key or value.
- valueType() returns the value type of the current key or value.
To read and process a file name scores.json
[
{
"first-name": "Ben",
"last-name": "Benson",
"year-of-birth": 1970,
"score": 86.765
},
{
"first-name": "Carl",
"last-name": "Carlson",
"year-of-birth": 1980,
"score": 91.201
}
]
Code
#include <iostream>
#include <Yson/JsonReader.hpp>
struct Person
{
std::string firstName;
std::string lastName;
int yearOfBirth;
double score;
};
Person deserializePerson(Yson::JsonReader& reader)
{
Person person;
// Enter the JSON object and make nextKey/nextValue apply there.
reader.enter();
// For each key in the object
while (reader.nextKey())
{
// Read the key
auto key = readValue<std::string>(reader);
// Advance the reader from the key to the value
reader.nextValue();
// Depending on the key, read the corresponding value
if (key == "first-name")
reader.readValue(person.firstName);
else if (key == "last-name")
reader.readValue(person.lastName);
else if (key == "year-of-birth")
reader.readValue(person.yearOfBirth);
else if (key == "score")
reader.readValue(person.score);
}
// Leave the JSON object an make nextKey/nextValue apply to the parent structure.
reader.leave();
return person;
}
int main()
{
std::vector<Person> persons;
try
{
// Open the file
Yson::JsonReader reader("scores.json");
// Advance to the top-level "value" in the file, i.e. the opening bracket.
if (!reader.nextValue())
return 1; //
// Enter the top-level array and make nextValue apply there.
reader.enter();
// Process each object inside the top-level array
while (reader.nextValue())
{
// Deserialize the Person in a separate function
persons.push_back(readPerson(reader));
}
// Leave the top-level array.
reader.leave();
}
catch (Yson::JsonReaderException& ex)
{
std::cerr << ex << "\n";
}
// ...
}
- nextToken() moves to the next token in the JSON contents, including whitespace and commas.
- tokenType() returns the type of the current token.
- token() returns the current token as string.
- comments, both //... and /.../
- multi-line strings """...."""
- special integer formats (0x... for hexadecimals, 0o... for octals and 0b... for binary numbers)
- non-string keys
- single-word keys without quotes
- multiple JSON top-level documents in a single file or stream (iterated over with nextDocument()).
- support for the special floating point values NaN and positive and negative inifinity.