With new technologies softwares need to evolve and adapt. My new task is to make cppagent generate output in Json (JavaScript Object Notation) format. Last week i spent sometime to try out different libraries and finally settled on using Rapidjson. Rapidjson is a json manipulation library for c++ which is fast, simple and has compatibility with different c++ compilers in different platforms. In this post we will be looking at example codes to generate, parse and manipulate json data. For people who want to use this library i would highly recommend them to play with and understand the example codes first.
First we will write a simple program to write a sample json as below (the same simplewriter.cpp as in example) :
{ "hello" : "world" , "t" : true , "f" : false , "i" : 123 , "pi" : 3.1416 , "a": [ 0, 1, 2, 3 ] }
To generate a Json output you need:
- a StringBuffer object, a buffer object to write the Json output.
- a Writer object to write Json to the buffer. Here i have used PrettyWriter object to write human-readable and properly indented json output.
- functions StartObject/EndObject to start and close a json object parenthesis “{” and “}” respectively.
- functions StartArray/EndArray to start and end a json array object i.e “[” and “]“.
- functions String(), Uint(), Bool(), Null() , Double() are called on writer object to write string, unsigned integer, boolean, null, floating point numbers respectively.
#include "rapidjson/stringbuffer.h" #include "rapidjson/prettywriter.h" #include <iostream> using namespace rapidjson; using namespace std; template <typename Writer> void display(Writer& writer ); int main() { StringBuffer s; PrettyWriter<StringBuffer> writer(s); display(writer); cout << s.GetString() << endl; // GetString() stringify the Json } template <typename Writer> void display(Writer& writer){ writer.StartObject(); // write "{" writer.String("hello"); // write string "hello" writer.String("world"); writer.String("t"); writer.Bool(true); // write boolean value true writer.String("f"); writer.Bool(false); writer.String("n"); writer.Null(); // write null writer.String("i"); writer.Uint(123); // write unsigned integer value writer.String("pi"); writer.Double(3.1416); // write floating point numbers writer.String("a"); writer.StartArray(); // write "[" for (unsigned i = 0; i < 4; i++) writer.Uint(i); writer.EndArray(); // End Array "]" writer.EndObject(); // end Object "}" }
Next we will manipulate the Json document and change the value for key “Hello” to “C++” ,
To manipulate:
- first you need to parse your json data into a Document object.
- Next you may use a Value reference to the value of the desired node/key or you can directly access them as doc_object[‘key’] .
- Finally you need to call the Accept method passing the Writer object to write the document to the StringBuffer object.
Below function changes the keywords for “hello” , “t”, “f” to “c++” , false , true respectively.
template <typename Document> void changeDom(Document& d){ // any of methods shown below can be used to change the document Value& node = d["hello"]; // using a reference node.SetString("c++"); // call SetString() on the reference d["f"] = true; // access directly and change d["t"].SetBool(false); // best way }
Now to put it all together:
Before Manupulation { "hello": "world", "t": true, "f": false, "n": null, "i": 123, "pi": 3.1416, "a": [ 0, 1, 2, 3 ] } After Manupulation { "hello": "c++", "t": false, "f": true, "n": null, "i": 123, "pi": 3.1416, "a": [ 0, 1, 2, 3 ] }
The final code to display the above output:
#include "rapidjson/stringbuffer.h" #include "rapidjson/prettywriter.h" #include "rapidjson/document.h" #include <iostream> using namespace rapidjson; using namespace std; template <typename Writer> void display(Writer& writer); template <typename Document> void changeDom(Document& d); int main() { StringBuffer s; Document d; PrettyWriter<StringBuffer> writer(s); display(writer); cout << "Before Manupulation\n" << s.GetString() << endl ; d.Parse(s.GetString()); changeDom(d); s.Clear(); // clear the buffer to prepare for a new json document writer.Reset(s); // resetting writer for a fresh json doc d.Accept(writer); // writing parsed document to buffer cout << "After Manupulation\n" << s.GetString() << endl; } template <typename Document> void changeDom(Document& d){ Value& node = d["hello"]; node.SetString("c++"); d["f"] = true; d["t"].SetBool(false); } template <typename Writer> void display(Writer& writer){ writer.StartObject(); writer.String("hello"); writer.String("world"); writer.String("t"); writer.Bool(true); writer.String("f"); writer.Bool(false); writer.String("n"); writer.Null(); writer.String("i"); writer.Uint(123); writer.String("pi"); writer.Double(3.1416); writer.String("a"); writer.StartArray(); for (unsigned i = 0; i < 4; i++) writer.Uint(i); writer.EndArray(); writer.EndObject(); }
[EDIT]
Added more complex examples in Understanding RapidJson – Part 2