-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add some example code that was prepared for a Melbourne C++ lightning…
… talk
- Loading branch information
1 parent
64abe84
commit cff81eb
Showing
6 changed files
with
508 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
/** | ||
* @file | ||
* | ||
* @brief Demonstrates iteration over an array and type check functions | ||
* | ||
*/ | ||
|
||
#include <exception> | ||
#include <iostream> | ||
|
||
// jsoncpp | ||
#include <json/json.h> | ||
#include <valijson/adapters/jsoncpp_adapter.hpp> | ||
#include <valijson/utils/jsoncpp_utils.hpp> | ||
|
||
// RapidJSON | ||
#include <rapidjson/document.h> | ||
#include <valijson/adapters/rapidjson_adapter.hpp> | ||
#include <valijson/utils/rapidjson_utils.hpp> | ||
|
||
using std::cerr; | ||
using std::cout; | ||
using std::endl; | ||
using std::runtime_error; | ||
|
||
// The first example uses RapidJson to load a JSON document. If the document | ||
// contains an array, this function will print any array values that have a | ||
// valid string representation. | ||
void usingRapidJson(const char *filename); | ||
|
||
// The second example uses JsonCpp to perform the same task, but unlike the | ||
// RapidJson example, we see how to use strict type checks and exception | ||
// handling. | ||
void usingJsonCpp(const char *filename); | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
if (argc != 2) { | ||
cerr << "Usage: " << endl; | ||
cerr << " " << argv[0] << " <filename>" << endl; | ||
return 1; | ||
} | ||
|
||
// Load the document using rapidjson | ||
cout << "-- Iteration using RapidJSON --" << endl; | ||
usingRapidJson(argv[1]); | ||
cout << endl; | ||
|
||
// Load the document using jsoncpp | ||
cout << "-- Iteration using jsoncpp --" << endl; | ||
usingJsonCpp(argv[1]); | ||
cout << endl; | ||
|
||
return 0; | ||
} | ||
|
||
void usingRapidJson(const char *filename) | ||
{ | ||
using valijson::adapters::RapidJsonAdapter; | ||
|
||
rapidjson::Document document; | ||
if (!valijson::utils::loadDocument(filename, document)) { | ||
return; | ||
} | ||
|
||
RapidJsonAdapter adapter(document); | ||
if (!adapter.isArray()) { | ||
cout << "Not an array." << endl; | ||
return; | ||
} | ||
|
||
cout << "Array values:" << endl; | ||
int index = 0; | ||
|
||
// We support the old way of doing things... | ||
const RapidJsonAdapter::Array array = adapter.asArray(); | ||
for (RapidJsonAdapter::Array::const_iterator itr = array.begin(); | ||
itr != array.end(); ++itr) { | ||
cout << " " << index++ << ": "; | ||
|
||
// Each element of the array is just another RapidJsonAdapter | ||
const RapidJsonAdapter &value = *itr; | ||
|
||
// maybeString is a loose type check | ||
if (value.maybeString()) { | ||
// If a value may be a string, we are allowed to get a string | ||
// representation of the value using asString | ||
cout << value.asString(); | ||
} | ||
|
||
cout << endl; | ||
} | ||
} | ||
|
||
void usingJsonCpp(const char *filename) | ||
{ | ||
Json::Value value; | ||
if (!valijson::utils::loadDocument(filename, value)) { | ||
return; | ||
} | ||
|
||
valijson::adapters::JsonCppAdapter adapter(value); | ||
|
||
// isArray is a strict type check | ||
if (!adapter.isArray()) { | ||
cout << "Not an array." << endl; | ||
return; | ||
} | ||
|
||
cout << "Array values:" << endl; | ||
int index = 0; | ||
|
||
// If a value is not an array, then calling getArray will cause a runtime | ||
// exception to be raised. | ||
for (auto value : adapter.getArray()) { | ||
cout << " " << index++ << ": "; | ||
|
||
// isString is another strict type check. Valijson uses the convention | ||
// that strict type check functions are prefixed with 'is'. | ||
if (!value.isString()) { | ||
cout << "Not a string. "; | ||
} | ||
|
||
try { | ||
// Also by convention, functions prefixed with 'get' will raise a | ||
// runtime exception if the value is not of the correct type. | ||
cout << value.getString() << endl; | ||
} catch (runtime_error &e) { | ||
cout << "Caught exception: " << e.what() << endl; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/** | ||
* @file | ||
* | ||
* @brief Demonstrates iteration over an array using template functions | ||
* | ||
*/ | ||
|
||
#include <iostream> | ||
|
||
#include <json/json.h> | ||
#include <valijson/adapters/jsoncpp_adapter.hpp> | ||
#include <valijson/utils/jsoncpp_utils.hpp> | ||
|
||
using std::cerr; | ||
using std::cout; | ||
using std::endl; | ||
|
||
template<class AdapterType> | ||
void iterateJsonArray(const AdapterType &adapter) | ||
{ | ||
if (!adapter.isArray()) { | ||
cout << "Not an array." << endl; | ||
return; | ||
} | ||
|
||
cout << "Array values:" << endl; | ||
int index = 0; | ||
|
||
for (auto value : adapter.getArray()) { | ||
cout << " " << index++ << ": "; | ||
|
||
if (value.maybeString()) { | ||
cout << value.asString(); | ||
} | ||
|
||
cout << endl; | ||
} | ||
} | ||
|
||
void usingJsonCppWithTemplateFn(const char *filename) | ||
{ | ||
Json::Value value; | ||
if (!valijson::utils::loadDocument(filename, value)) { | ||
return; | ||
} | ||
|
||
valijson::adapters::JsonCppAdapter adapter(value); | ||
iterateJsonArray(adapter); | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
if (argc != 2) { | ||
cerr << "Usage: " << endl; | ||
cerr << " " << argv[0] << " <filename>" << endl; | ||
return 1; | ||
} | ||
|
||
// Load the document using jsoncpp and iterate over array using function template | ||
cout << "-- Array iteration using jsoncpp via template function --" << endl; | ||
usingJsonCppWithTemplateFn(argv[1]); | ||
cout << endl; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/** | ||
* @file | ||
* | ||
* @brief Demonstrates how to resolve JSON pointers against the current document | ||
* | ||
*/ | ||
|
||
#include <iostream> | ||
|
||
#include <rapidjson/document.h> | ||
|
||
#include <valijson/adapters/rapidjson_adapter.hpp> | ||
#include <valijson/internal/json_pointer.hpp> | ||
#include <valijson/internal/json_reference.hpp> | ||
#include <valijson/utils/rapidjson_utils.hpp> | ||
|
||
using std::cerr; | ||
using std::cout; | ||
using std::endl; | ||
|
||
template<typename AdapterType> | ||
std::string maybeResolveRef(const AdapterType &value, const AdapterType &root) | ||
{ | ||
if (!value.isObject()) { | ||
// Not an object, therefore not a JSON reference | ||
return ""; | ||
} | ||
|
||
const auto &object = value.getObject(); | ||
const auto itr = object.find("$ref"); | ||
if (itr == object.end()) { | ||
// Object does not contain $ref property | ||
return ""; | ||
} | ||
|
||
const AdapterType maybeRef = itr->second; | ||
if (!maybeRef.isString()) { | ||
return "[$ref did not contain a string value]"; | ||
} | ||
|
||
// Attempt to extract a JSON pointer | ||
const std::string ref = maybeRef.getString(); | ||
const auto maybePointer = valijson::internal::json_reference::getJsonReferencePointer(ref); | ||
if (!maybePointer) { | ||
return "[$ref did not contain valid JSON pointer]"; | ||
} | ||
|
||
const auto refAdapter = valijson::internal::json_pointer::resolveJsonPointer(root, *maybePointer); | ||
if (!refAdapter.maybeString()) { | ||
return "[$ref did not point to a string value]"; | ||
} | ||
|
||
return refAdapter.asString(); | ||
} | ||
|
||
template<typename AdapterType> | ||
void iterateJsonObject(const AdapterType &adapter) | ||
{ | ||
if (!adapter.maybeObject()) { | ||
cout << "Not an object." << endl; | ||
return; | ||
} | ||
|
||
cout << "Object members:" << endl; | ||
|
||
// JSON objects are an unordered collection of key-value pairs, | ||
// so the members of the object may be printed in an order that is | ||
// different to that in the source JSON document. | ||
for (auto member : adapter.asObject()) { | ||
// The key is a std::string that can be accessed using 'first' | ||
cout << " " << member.first << ": "; | ||
|
||
// The value is just another Adapter, and can be accessed using 'second' | ||
const AdapterType &value = member.second; | ||
if (value.maybeString()) { | ||
cout << value.asString(); | ||
} else { | ||
cout << maybeResolveRef(value, adapter); | ||
} | ||
|
||
cout << endl; | ||
} | ||
} | ||
|
||
void usingJsonCppWithTemplateFn(const char *filename) | ||
{ | ||
rapidjson::Document document; | ||
if (!valijson::utils::loadDocument(filename, document)) { | ||
return; | ||
} | ||
|
||
valijson::adapters::RapidJsonAdapter adapter(document); | ||
iterateJsonObject(adapter); | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
if (argc != 2) { | ||
cerr << "Usage: " << endl; | ||
cerr << " " << argv[0] << " <filename>" << endl; | ||
return 1; | ||
} | ||
|
||
// Load the document using jsoncpp and iterate over array using function template | ||
cout << "-- Resolving JSON pointers using RapidJSON --" << endl; | ||
usingJsonCppWithTemplateFn(argv[1]); | ||
cout << endl; | ||
|
||
return 0; | ||
} |
Oops, something went wrong.