Main  /  Edit  /  History  /   /  Users Area

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:

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:

  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
}

Serialization | Top | JSON RPC

About

CppCMS is a web development framework for performance demanding applications.

Support This Project

SourceForge.net Logo

Поддержать проект

CppCMS needs You


Navigation

Main Page



Valid CSS | Valid XHTML 1.0