History v 1.0 |
|
---|---|
2015-12-29 |
New feature: Simple XPath-style access with operator[str_type]:
|
2015-12-28 |
Changed Building requirements:
|
This page gives a brief overview of the library and contains some samples on how to use it.
First of all there are some assumptions and constraints made by the library's class implementation.
To use the library you should be familiar with the JSON format in general.
For details refer to:
- https://de.wikipedia.org/wiki/JavaScript_Object_Notation
- http://json.org/
(The manual itself will not go into much details for that).
To use the library, you need a C++ compiler (supporting C++11 or newer) and link the json-library to your sources (see chapter Samples
).
The library is designed to be used as a static linker library, since it uses template classes.
The JSON library is provided as is without any warranties of accurately support
all features the JSON format may allow.
I spent some time to support even the parsing of numbers with fractional and
exponential values and to support special unicode characters given by "\uXXXX"
.
\uXXXX
is known but not supported yet. Bilding the Library
)\uXXXX
). operator[str_type]
, but probably with an additional XPATH-like style. To retrieve the value in a complete hierarchical structure by just using something like settings/local/Key
.To build the library you will need at least Visual Studio 2015 or 2010 (express versions should do).
Other compilers may work, but I didn't test them yet.
If you make the library compile with another compiler, please let me know, drop me a line
and/or send me the makefile together with version of you compiler and system :)
The SVN repository uses external
s referencing the dtitem-library project.
By downloading a snapshot of json-library you will not get these externals. To build, download also a snapshot of
the dtitem library and copy the contents of the dtitem/src
folder to json/external
.
In the library a JSON Object is a class of js::json
.
All classes used in the library are located in namespace 'js'
.
All strings in the library are of type js::str_type
.
Whenever the library will support UTF-8 (or even better UTF-16) character encoding strings/files, js::str_type
may be changed from std::string
to std::wstring
, i.e. better use js::str_type
instead of std::string
.
There are several constructors and creation methods available.
One can use e.g. std::string
to create an instance of class json
or
reading the contents of a file to create it (refer to js::json::from_string()
, js::json::from_file()
).
There are also methods to retrieve a (nicely formatted) string back from
an existing json object or directly save it to a file (refer to js::json::to_string()
, js::json::to_file()
).
To get access to the data values included in a json
object, there exists several methods.
The most easy-to-use method is using json::operator[]
, that allows you to navigate to the object's sub items in such a way you would do with a standard multi-dimensional C++ array (refer to js::json::operator[]
, js::json::at()
).
Another way is to access a container of type object or array is to use the related access methods directly (refer to js::json::object()
, js::json::array()
, js::json::value()
).
Using these methods assumes that you know the exact format of the loaded JSON data.
If you don't, you may iterate the json
object by using the related iteration methods and check the name for each sub item manually (refer to js::json::count()
, js::json::at()
, js::json::name()
).
This is currently not supported and there are no plans to add them in the next
releases.
All constructors and creation methods may throw exceptions.
All thrown exceptions are derived from std::exception
.
You should consider to handle std::exception
throwings wise.
All manually thrown exceptions are of one of these types:
- js::ex_parser
(the string or file parser cannot identify a symbol or wrong JSON format detected)
- js::ex_generator
(the json
putted in the generator is malformed (should never happen)
- js::ex_conversion
(e.g. you want explicitely read an integer but the JSON value points to s string instead)
Internally the json
class uses a std::shared_ptr<>
descendant that holds
the contents of the object.
When copying or assigning a json
object to another object or a sub item to another object,
usually only the reference count of those objects will be increased and the data
will not being copied.
Most of the access methods create sub items and return a new instance of a
json
object, which makes heavy use of recursion calls internally.
The JSON library is based on the [[DataItem library]] for its internal references, or you
might want to say the DataItem library consists of a type of serialization using the
JSON library.
In fact, I started with the JSON library first for the purpose to have a
easy-to-use serialization format.
After a while I noticed the DataItem library's dt::dtitem
class is much more
flexible than the JSON format can be. Nevertheless a JSON parser is a cool
small project :)
Here are some sample C++ sources, just for given a first impression about the functions.
Refer for details to the complete doxygen documentation as provided.
Including json.h declares all classes and methods in namespace js but
also adds some using statements to export these to the global namespace.
#include "json.h"
This sample shows how to use the most simple expression "{}"
to create a json
of type object from. Then it prints out the name() and the count() of sub items (in this case 0).
void create_simple_object()
{
str_type str = "{}";
json mobject = json::from_string(str);
std::cout << "Created a json object from string "
<< "'" << str << "', "
<< "name = " << mobject.name() << ", "
<< "children = " << mobject.count() << std::endl;
}
==> >Created a json object from string '{}', name = object, children = 0
Identical to the previous sample but uses the expression "[]"
to create a json
of type array from.
void create_simple_array()
{
str_type str = "[]";
json marray = json::from_string(str);
std::cout << "Created a json object from string "
<< "'" << str << "', "
<< "name = " << marray.name() << ", "
<< "children = " << marray.count() << std::endl;
}
==> >Created a json object from string '[]', name = array, children = 0
The next one initializes a json
instance with type object containing two pairs. Showing also how to use the direct access method operator[]
:
void create_key_value_pairs()
{
str_type str = "{ \"Key1\" : \"Value1\", \"Key2\" : \"Value2\" }";
json mobject = json::from_string(str);
std::cout << "Created json object with name = "
<< mobject.name() << ", "
<< "children = " << mobject.count() << std::endl;
//> ... name = object, children = 2
json mpair = mobject[0]; // <-- 1st pair
std::cout << "First item of object: name = "
<< mpair.name() << ", key = "
<< mpair.key() << std::endl;
//> ... name = pair, key = Key1
mpair = mobject[1]; // <-- 2nd pair
std::cout << "Second item of object: name = "
<< mpair.name() << ", key = "
<< mpair.key() << std::endl;
//> ... name = pair, key = Key2
// Shortcuts to retrieve the values by index not
// using the pair objects
std::cout << "First pair's value = "
<< (str_type)mobject[0] // <-- shortcut to value
<< std::endl;
//> ... value = Value1
std::cout << "Second pair's value = "
<< (str_type)mobject[1] // <-- shortcut to value
<< std::endl;
//> ... value = Value2
}
void object_in_object_xpath()
{
js::str_type s = "{ \"x\" : { \"y\" : 22 } }";
// an object in an object
// { "x" : { "y" : 22 } }
js::json myJSON = json::from_string(s);
// use xpath expression x/y ==> pair("y" : 22)
js::str_type xpath("x/y");
js::json myPair = myJSON[xpath];
// check that we got a pair
assert(myPair.name() == js::str_type("pair"));
// retrieve the value of the pair (use operator int)
int myIVal = myPair;
assert(myIVal == 22);
// or the complete function in one line...
myIVal = myJSON["x/y"];
assert(myIVal == 22);
}
void array_in_multiple_objects_xpath()
{
js::str_type s = "{ \"x\" : { \"y\" : [ \"a\", true ] } }";
// an array in an object in an object
// { "x" : { "y" : [ "a", true, false, null, 234.456 ] } }
js::json myJSON = json::from_string(s);
// use xpath expression x/y[1] ==> array value[1] ==> true
js::str_type xpath("x/y[1]");
js::json myValue = myJSON[xpath];
// check that we got the true constant
assert(myValue.name() == js::str_type("true"));
// retrieve the value
bool value = myValue;
assert(true == value);
// or the complete function in one line...
value = myJSON["x/y[1]"];
assert(true == value);
}
void object_in_array_in_multiple_objects_xpath()
{
js::str_type s = "{ \"x\" : { \"y\" : [ \"a\", { \"KEY\":\"VALUE\", \"One\" : 1 } ] } }";
// an object in an array in an object in an object
// { "x" : { "y" : [ "a", { "KEY" : "VALUE", "One" : 1 } ] } }
js::json myJSON = json::from_string(s);
// use xpath expression x/y[1]/KEY
// ==> inner object value[ 1 ]
// ==> Pair ("KEY" : "VALUE")
js::str_type xpath("x/y[1]/KEY");
js:json myPair = myJSON[xpath];
// check, that we got the correct object
assert(myPair.name() == js::str_type("pair"));
// retrieve the key and value
js::str_type key = myPair.key();
assert(key == js::str_type("KEY"));
js::str_type value = myPair; // <-- per default this point to a value (if the json object is of type "pair")
assert(value == js::str_type("VALUE"));
// or the complete function in one line...
value = myJSON["x/y[1]/KEY"];
assert(value == js::str_type("VALUE"));
}