JSON
Introduction
JSON is a lightweight structured data interchange format. Unlike XML it is very easy to parse format. More then that in comparison to XML it contains much higher signal to noise ratio.
CppCMS recommend using JSON as data interchange format
and it uses this format for CppCMS configuration file
that is accessible via cppcms::service::settings()
member function.
CppCMS provides a powerful class cppcms::json::value
that
allows to format, parse and operate over JSON data.
Operating On JSON data.
There are three major objects in cppcms::json
namespace:
value
- the universal container that can hold objects, arrays and scalar valuesarray
-std::vector<value>
- array of valuesobject
-std::map<string_key,value>
- mapping between strings and values.
For given:
cppcms::json::value my_object;
We can easily add new members to our object:
my_object["name"]="Moshe"; my_object["salary"]=1000.0; my_object["kids_names"][0]="Yossi"; my_object["kids_names"][1]="Yonni"; my_object["data"]["weight"]=85; my_object["data"]["height"]=1.80;
With this small code we created an object like:
{ "name" : "Moshe", "salary" : 1000.0, "kids_names" : [ "Yossi" , "Yonni" ], "data" : { "weight" : 85, "height" : 1.80 } }
When we access operator []
of non-const object we
automatically create a JSON object or JSON array depending
on the type of the parameter (textual - object, numerical - array).
The array is automatically extended when we try to access "empty" spots.
We can easily access values using operator []
and
member functions like number()
, for example:
double salary = my_object["salary"].number(); std::string name = my_object["name"].str();
Or we can use get
member function and specify a full
path to the required object:
double salary = my_object.get<double>("salary"); double height = my_object.get<double>("data.height");
We can also provide some default values in case the given path does not exist or has different type:
std::string eyes_color = my_object.get("data.eyes_color","brown");
JSON Input and Output
cppcms::json::value
has operators >>
and <<
with std::istream
and std::ostream
respectively,
so you can easily save JSON data as:
out << my_object
And read it as
in >> my_object
You can also use save
and load
member functions
to have greater control over the way the objects are written
and read.
For example, pretty print JSON object:
my_object.save(std::cout,cppcms::json::readable);
Read the input and make sure we got to EOF:
my_object.load(tmp,true);
C++ Class JSON Object conversion
It is possible to define a conversion between C++ and
JSON objects. It can be done by specializing
cppcms::json::traits
class.
For example, we have a object person:
struct person { std::string name; double salary; std::vector<std::string> kids_names; };
We can define a method for converting between person
and cppcms::json::value
by specializing the traits
class:
namespace cppcms { namespace json { template<> struct traits<person> { ... }; } // json } // cppcms
The specialized traits class should include two static
member functions get
and set
:
The "getter:"
static person get(value const &v) { person p; if(v.type()!=is_object) throw bad_value_cast(); p.name=v.get<std::string>("name"); p.salary=v.get<double>("salary"); p.kids_names= v.get<std::vector<std::string> >("kids_names"); return p; }
First we check that the type is "Object" otherwise
we throw bad_value_cast
. Note this step is not
really necessary as v.get<std::string>("name")
would
throw bad_value_cast
in case v
is not an object.
But it is useful to see how errors should be reported: by
throwing cppcms::json::bad_value_cast
.
Then we setup different member functions.
Note this line:
v.get<std::vector<std::string> >("kids_names");
It works because std::vector
and many other standard
C++ containers are already specialized so std::vector<std::string>
is expected to be an
array of JSON strings.
Our setter is similar:
static void set(value &v,person const &in) { v.set("name",in.name); v.set("salary",in.salary); v.set("kids_names",in.kids_names); }
As above we save std::vector<std::string>
automatically.
Now we can convert between value
and person as
any other scalar before:
person moshe = my_object.get_value<person>(); some_object["stuff"]["head"] = moshe; moshe = some_object.get<moshe>("stuff.head");
Further Reading
Take a look JSON Namespace reference manual.
Syntax Extensions
CppCMS supports some non-standard JSON syntax that makes it suitable for configuration file format:
- It allows C++ style comments
//
- It allows trailing commas in objects and arrays.
Thus following syntax is accepted by the JSON parser:
{ "foo" : 10, "bar" : 20, // Note trailing comma // "baz" : 30 -- this is a comment }
← Serialization | Top | JSON RPC →