tutorial.cpp 6.04 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Hello World example
// This example shows basic usage of DOM-style API.

#include "rapidjson/document.h"		// rapidjson's DOM-style API
#include "rapidjson/prettywriter.h"	// for stringify JSON
#include "rapidjson/filestream.h"	// wrapper of C stream for prettywriter as output
#include <cstdio>

using namespace rapidjson;

11
int main(int, char*[]) {
12 13 14 15 16 17 18 19 20 21
	////////////////////////////////////////////////////////////////////////////
	// 1. Parse a JSON text string to a document.

	const char json[] = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
	printf("Original JSON:\n %s\n", json);

	Document document;	// Default template parameter uses UTF8 and MemoryPoolAllocator.

#if 0
	// "normal" parsing, decode strings to new buffers. Can use other input stream via ParseStream().
22
	if (document.Parse(json).HasParseError())
23 24 25
		return 1;
#else
	// In-situ parsing, decode strings directly in the source string. Source must be string.
26 27 28
	{
		char buffer[sizeof(json)];
		memcpy(buffer, json, sizeof(json));
29
		if (document.ParseInsitu(buffer).HasParseError())
30 31
			return 1;
	}
32 33 34 35 36 37 38 39 40 41 42 43 44 45
#endif

	printf("\nParsing to document succeeded.\n");

	////////////////////////////////////////////////////////////////////////////
	// 2. Access values in document. 

	printf("\nAccess values in document:\n");
	assert(document.IsObject());	// Document is a JSON value represents the root of DOM. Root can be either an object or array.

	assert(document.HasMember("hello"));
	assert(document["hello"].IsString());
	printf("hello = %s\n", document["hello"].GetString());

46 47 48 49 50
	// Since version 0.2, you can use single lookup to check the existing of member and its value:
	Value::Member* hello = document.FindMember("hello");
	assert(hello != 0);
	assert(hello->value.IsString());
	assert(strcmp("world", hello->value.GetString()) == 0);
51
	(void)hello;
52

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
	assert(document["t"].IsBool());		// JSON true/false are bool. Can also uses more specific function IsTrue().
	printf("t = %s\n", document["t"].GetBool() ? "true" : "false");

	assert(document["f"].IsBool());
	printf("f = %s\n", document["f"].GetBool() ? "true" : "false");

	printf("n = %s\n", document["n"].IsNull() ? "null" : "?");

	assert(document["i"].IsNumber());	// Number is a JSON type, but C++ needs more specific type.
	assert(document["i"].IsInt());		// In this case, IsUint()/IsInt64()/IsUInt64() also return true.
	printf("i = %d\n", document["i"].GetInt());	// Alternative (int)document["i"]

	assert(document["pi"].IsNumber());
	assert(document["pi"].IsDouble());
	printf("pi = %g\n", document["pi"].GetDouble());

	{
		const Value& a = document["a"];	// Using a reference for consecutive access is handy and faster.
		assert(a.IsArray());
		for (SizeType i = 0; i < a.Size(); i++)	// rapidjson uses SizeType instead of size_t.
			printf("a[%d] = %d\n", i, a[i].GetInt());
		
		// Note:
		//int x = a[0].GetInt();					// Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type.
		int y = a[SizeType(0)].GetInt();			// Cast to SizeType will work.
		int z = a[0u].GetInt();						// This works too.
79 80
		(void)y;
		(void)z;
81 82 83 84 85 86

		// Iterating array with iterators
		printf("a = ");
		for (Value::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
			printf("%d ", itr->GetInt());
		printf("\n");
87 88
	}

89 90 91 92 93 94
	// Iterating object members
	static const char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" };
	for (Value::ConstMemberIterator itr = document.MemberBegin(); itr != document.MemberEnd(); ++itr)
		printf("Type of member %s is %s\n", itr->name.GetString(), kTypeNames[itr->value.GetType()]);

	////////////////////////////////////////////////////////////////////////////
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
	// 3. Modify values in document.

	// Change i to a bigger number
	{
		uint64_t f20 = 1;	// compute factorial of 20
		for (uint64_t j = 1; j <= 20; j++)
			f20 *= j;
		document["i"] = f20;	// Alternate form: document["i"].SetUint64(f20)
		assert(!document["i"].IsInt());	// No longer can be cast as int or uint.
	}

	// Adding values to array.
	{
		Value& a = document["a"];	// This time we uses non-const reference.
		Document::AllocatorType& allocator = document.GetAllocator();
		for (int i = 5; i <= 10; i++)
			a.PushBack(i, allocator);	// May look a bit strange, allocator is needed for potentially realloc. We normally uses the document's.

		// Fluent API
		a.PushBack("Lua", allocator).PushBack("Mio", allocator);
	}

	// Making string values.

	// This version of SetString() just store the pointer to the string.
	// So it is for literal and string that exists within value's life-cycle.
	{
		document["hello"] = "rapidjson";	// This will invoke strlen()
		// Faster version:
		// document["hello"].SetString("rapidjson", 9);
	}

	// This version of SetString() needs an allocator, which means it will allocate a new buffer and copy the the string into the buffer.
	Value author;
	{
		char buffer[10];
		int len = sprintf(buffer, "%s %s", "Milo", "Yip");	// synthetic example of dynamically created string.

133
		author.SetString(buffer, static_cast<size_t>(len), document.GetAllocator());
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
		// Shorter but slower version:
		// document["hello"].SetString(buffer, document.GetAllocator());

		// Constructor version: 
		// Value author(buffer, len, document.GetAllocator());
		// Value author(buffer, document.GetAllocator());
		memset(buffer, 0, sizeof(buffer)); // For demonstration purpose.
	}
	// Variable 'buffer' is unusable now but 'author' has already made a copy.
	document.AddMember("author", author, document.GetAllocator());

	assert(author.IsNull());		// Move semantic for assignment. After this variable is assigned as a member, the variable becomes null.

	////////////////////////////////////////////////////////////////////////////
	// 4. Stringify JSON

	printf("\nModified JSON with reformatting:\n");
	FileStream f(stdout);
	PrettyWriter<FileStream> writer(f);
	document.Accept(writer);	// Accept() traverses the DOM and generates Handler events.

	return 0;
}