<!--toc--> |
|
## Introduction |
|
[JSON](http://json.org/) 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 values |
- `array` - `std::vector<value>` - array of values |
- `object` - `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 grater 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](/cppcms_ref_v0_99/namespacecppcms_1_1json.html) reference manual. |
|
## Syntax Extensions |
|
CppCMS supports some non-standard JSON syntax that makes |
it suitable for configuration file format: |
|
1. It allows C++ style comments `//` |
2. 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 |
} |
|
|
|