TinyJSON is a fast and small C++ JSON parser
See more in the specifications document.
One of the important change is that prior to RFC 8259 only objects and arrays could be at the root.
{
"meaning" : 42
}or
[
42, 12, 3.14
]But since RFC 8259 any of the other elements are valid, (string, true, false, null, number)
true| JSON | c++/TinyJSON |
|---|---|
| object | TJValueObject |
| array | TJValueArray |
| string | TJValueString |
| number | TJValueNumber (longl long, long double, exponent) |
| true | TJValueBoolean (true) |
| false | TJValueBoolean (false) |
| null | TJValueNull (nullptr) |
We follow Semantic Versioning 2.0.0, semver.org
- MAJOR version when you make incompatible API changes
- MINOR version when you add functionality in a backward compatible manner
- PATCH version when you make backward compatible bug fixes
The version is set in the TinyJSON.h file.
static const short TJ_VERSION_MAJOR = 0;
static const short TJ_VERSION_MINOR = 0;
static const short TJ_VERSION_PATCH = 1;
static const char TJ_VERSION_STRING[] = "0.0.1";- Depth: (
max_depth:64) You can set how deep you want to allow the parsing to go. - Throw: (
throw_exception:false) If you want to throw exceptions or simply return null. - Specification: (
specification:parse_options::rfc8259) What specs will the parser be following/enforcing.- rfc4627
- rfc7159
- rfc8259
For example ...
TinyJSON::parse_options options = {};
options.throw_exception = true;
options.max_depth = 10;
try
{
auto blah = TinyJSON::TJ::parse("[0123]", options)
...
}
catch(TinyJSON::TJParseException ex)
{
ex.what(); // Numbers cannot have leading zeros
}- Throw: (
throw_exception:false) If you want to throw exceptions or simply return false. - write_formating: (
write_formating::indented) The formating we want to write the file with.- none
- indented
- Byte order mark: (
byte_order_mark:none)- none
- uft8
For example ...
TinyJSON::write_options options = {};
options.throw_exception = true;
options.write_formating = TinyJSON::formating::minify;
try
{
...
// get JSON somewhere or create it.
...
if( TinyJSON::TJ::write_file("file.json", *json, options))
{
// all good
}
...
}
catch(TinyJSON::TJParseException ex)
{
ex.what(); // what?
}The parsing exception is TinyJSON::TJParseException and can be made optional in the TinyJSON::parse_options flag.
TinyJSON::parse_options options = {};
options.throw_exception = true;
try
{
auto blah = TinyJSON::TJ::parse("[0123]", options)
...
}
catch(TinyJSON::TJParseException ex)
{
ex.what(); // Numbers cannot have leading zeros
}The parsing exception is TinyJSON::TJParseException and can be made optional in the TinyJSON::parse_options flag.
TinyJSON::write_options options = {};
options.throw_exception = true;
options.write_formating = TinyJSON::formating::minify;
try
{
auto json = TinyJSON::TJ::parse( "{ \"Hello\" : \"World\" }" );
TinyJSON::TJ::write_file("file.json", *json, options)
...
}
catch(TinyJSON::TJWriteException ex)
{
ex.what(); // some write error
}You can simply call the TinyJSON::TJ::is_valid(...) method
if(TinyJSON::TJ::is_valid("[123,456]"))
{
// do this
}
else
{
// do that
}To read a JSON file you simply need to call the static method parse_file, the extention does not have to be .json
auto json = TinyJSON::TJ::parse_file( "myfile.json" );
...
delete json;This will then return an object that you can inspect as per normal.
To read a JSON string you simply need to call the static method parse
auto json = TinyJSON::TJ::parse( "{ \"Hello\" : \"World\" }" );
...
delete json;This will then return an object that you can inspect.
...
auto value = json->try_get_string("Hello"); // "World"
auto no_value = json->try_get_string("Life"); // null
...You can also use literals
using namespace TinyJSON;
...
auto json = "[12,13,14]"_tj;
// use it.
...
delete json;
...Or just use the string directly
You can convert the json to 'pretty' indented json
#define TJ_INCLUDE_STD_STRING 1
#include "TinyJSON.h"
using namespace TinyJSON;
...
// output a pretty JSON
std::cout << "[12,13,14]"_tj_indent;
...Or minify code.
#define TJ_INCLUDE_STD_STRING 1
#include "TinyJSON.h"
using namespace TinyJSON;
...
// output a pretty JSON
std::cout << "[12 , 13 , 14]"_tj_minify;
...There are 2 ways to find a key, case sensitive or insensitive, (the default is case sensitive).
You can load the json either by parsing or creating it manually.
auto object = new TinyJSON::TJValueObject();
object->set_string("a", "Hello");
object->set_string("b", "World");
object->set_string("c", "Bye");
...
// search for something
auto case_sensitive = object->try_get_value("Hello");
auto case_insensitive = object->try_get_value("HelLO", false); // all good as we don't care about case.
auto case_insensitive_not_found = object->try_get_value("HelLO"); // = null as the search was case sensitive
...
delete object; auto object = new TinyJSON::TJValueObject();
object->set_string("a", "Hello");
object->set_string("b", "World");
object->set_string("c", "Bye");
object->set_boolean("d", true);
object->set_float("e", 42.15);
auto dump = object->dump();
/*
{
"a": "Hello",
"b": "World",
"c": "Bye",
"d": true,
"e": 42.15
}
*/You can also remove a value
auto object = new TinyJSON::TJValueObject();
object->set_string("a", "Hello");
object->set_string("b", "World");
object->set_string("c", "Bye");
object->set_boolean("d", true);
object->pop("b");
auto dump = object->dump();
/*
{
"a": "Hello",
"b": "World",
"c": "Bye",
"d": true
}
*/To write a JSON string you simply need to call the method write_file on the JSON object returned.
auto json = TinyJSON::TJ::parse( "{ \"Hello\" : \"World\" }" );
if( TinyJSON::TJ::write_file("file.json", *json))
{
// all good
}
else
{
// something broke
}
delete json;Regardless if you are parsing a file or parsing a string, TinyJSON will parse the file for UTF-8 DOM if there is one.
While you can dump a string to (re)write a json string you might want to use it directly in your code.
auto json = TinyJSON::TJ::parse( R"("This is a test \" with a quote")" );
auto actual_string = json->dump_string();
/*
This is a test " with a quote
*/
delete json;The formating types are
TinyJSON::formating::indented
TinyJSON::formating::minifyEach objects are read into TJValue* classes of type TJValueObject.
auto json = TinyJSON::TJ::parse( "{ \"Hello\" : \"World\" }" );
auto value = json->try_get_string("Hello"); // "World"
auto no_value = json->try_get_string("Life"); // null
delete json;or
auto json = TinyJSON::TJ::parse( "{ \"Hello\" : \"World\" }" );
auto value = json->get_string("Hello"); // "World"
auto no_value = json->get_string("Life", true, false); // null
delete json;You can dynamically create a new object and then add a named values to it.
auto object = new TinyJSON::TJValueObject();
object->set_number("a", 42);
object->set_float("b", 0.005);
object->set_null("c");
...
delete json;Each arrays are read into TJValue* classes of type TJValueArray.
Then each items in the array are also TJValue* of type string, number and so on.
auto json = TinyJSON::TJ::parse( "[ 12, 14, 16 ]" );
auto array_of_values = dynamic_cast<TinyJSON::TJValueArray*>(json);
auto number_of_items = array_of_values->get_number_of_items(); // 3
auto value1 = array_of_values->at(0); //14
auto value2 = array_of_values->at(2); //16
auto value3 = array_of_values->at(5); // null
delete json;You can dynamically create a new array and then add string, numbers and so on.
auto json = new TinyJSON::TJValueArray();
json->add_boolean(true);
json->add_boolean(false);
json->add_number(42);
...
delete json;Each TJValue* item can be of different type
Assuming the array below with multiple items, you can query the type of each TJValue* and do something accordingly.
auto json = TinyJSON::TJ::parse( "[ ... ]" );
auto array_of_values = dynamic_cast<TinyJSON::TJValueArray*>(json);
auto value = array_of_values->at(0);
if(value->is_object()) { /**/}
if(value->is_array()) { /**/}
if(value->is_string()) { /**/}
if(value->is_number()) { /**/}
if(value->is_true()) { /**/}
if(value->is_false()) { /**/}
if(value->is_null()) { /**/}
delete json;You can get a value from any TJValue*, (as long as the value can actually be converted)
- get_number()
- get_float()
- get_string()
- get_boolean()
- get_numbers()
- get_floats()
auto json = TinyJSON::TJ::parse(R"(
{
"a": true,
"b": 123,
"c": 0,
"d": 42.2
}
)"
);
auto valuea = jobject->try_get_value("a");
if( valuea->get_boolean())
{
// value a is true
}
auto valuea = jobject->try_get_value("b");
if( valueb->get_boolean())
{
// value b is not a boolean but it is non zero
}
auto json = TinyJSON::TJ::parse(R"(
{
"a": true,
"b": 123,
"c": 0,
"d": 42.2
}
)"
);
auto valuea = jobject->try_get_value("a");
if( valuea->get_boolean())
{
// value a is true
}
auto valuea = jobject->try_get_value("b");
if( valueb->get_boolean(true)) // THROW! "b" is not a boolean
{
// value b is not a boolean but it is non zero
}
This can be helpful is you are looking for a certain data type.
All you need is to include the .h and .cpp file to your project and you are ready to go.
- Clone this repository
- init the submodules
git submodule --init --recursive
The whole number ranges are +9223372036854775807 and -9223372036854775806
- Make sure that all the code follow our own coding standards.
- [] Update comments
- Finish documentation how to use the code.
- [] Run/Create some benchmark tests, make sure they are up to date.
- Arrays
- Objects
- Values
- More tests!
- Add version number (started at version 0.0.1)
- Copyright
- Add 2 kinds of error handling, either throw or return an error structure.
- [] While we do not care about size, (on paper), it would be nice to implement limits in the code.
- depth
- [] string
- [] numbers
- Automated build
- Run on linux/gcc/g++ or something other than visual studio.
g++ -std=c++11 -Wall -Wextra -Werror -O3 src/tinyJSON.cpp -o a.exe - [] We need to add copy and move constructors to
TJValueand the derived classes. - [] Add Macro(s) explaination like
TJ_INCLUDE_STD_STRINGfor example. - [] Add support for JSON5 https://json5.org 📄 https://github.com/json5/json5