JSONDoc is a convenient reader/writer class for manipulating JSON documents using "paths". Access is done using a "path", which is a string of dot-separated substrings representing representing successively deeper keys found in nested JSON objects within the top level object Most methods are read-only with respect to the source JSON object. The only modifying methods are create(), put(), subDoc()
| 67 | // // The following would throw if a.b.c did not exist, or if it was not an int. |
| 68 | // int x = r["a.b.c"].get_int(); |
| 69 | struct JSONDoc { |
| 70 | JSONDoc() : pObj(nullptr) {} |
| 71 | |
| 72 | // Construction from const json_spirit::mObject, trivial and will never throw. |
| 73 | // Resulting JSONDoc will not allow modifications. |
| 74 | JSONDoc(const json_spirit::mObject& o) : pObj(&o), wpObj(nullptr) {} |
| 75 | |
| 76 | // Construction from json_spirit::mObject. Allows modifications. |
| 77 | JSONDoc(json_spirit::mObject& o) : pObj(&o), wpObj(&o) {} |
| 78 | |
| 79 | // Construction from const json_spirit::mValue (which is a Variant type) which will try to |
| 80 | // convert it to an mObject. This will throw if that fails, just as it would |
| 81 | // if the caller called get_obj() itself and used the previous constructor instead. |
| 82 | JSONDoc(const json_spirit::mValue& v) : pObj(&v.get_obj()), wpObj(nullptr) {} |
| 83 | |
| 84 | // Construction from non-const json_spirit::mValue - will convert the mValue to |
| 85 | // an object if it isn't already and then attach to it. |
| 86 | JSONDoc(json_spirit::mValue& v) { |
| 87 | if (v.type() != json_spirit::obj_type) |
| 88 | v = json_spirit::mObject(); |
| 89 | wpObj = &v.get_obj(); |
| 90 | pObj = wpObj; |
| 91 | } |
| 92 | |
| 93 | // Returns whether or not a "path" exists. |
| 94 | // Returns true if all elements along path exist |
| 95 | // Returns false if any elements along the path are MISSING |
| 96 | // Will throw if a non-terminating path element exists BUT is not a JSON Object. |
| 97 | // If the "split" flag is set to "false", then this skips the splitting of a |
| 98 | // path into on the "dot" character. |
| 99 | // When a path is found, pLast is updated. |
| 100 | bool has(std::string path, bool split = true) { |
| 101 | if (pObj == nullptr) |
| 102 | return false; |
| 103 | |
| 104 | if (path.empty()) |
| 105 | return false; |
| 106 | size_t start = 0; |
| 107 | const json_spirit::mValue* curVal = nullptr; |
| 108 | while (start < path.size()) { |
| 109 | // If a path segment is found then curVal must be an object |
| 110 | size_t dot; |
| 111 | if (split) { |
| 112 | dot = path.find_first_of('.', start); |
| 113 | if (dot == std::string::npos) |
| 114 | dot = path.size(); |
| 115 | } else { |
| 116 | dot = path.size(); |
| 117 | } |
| 118 | std::string key = path.substr(start, dot - start); |
| 119 | |
| 120 | // Get pointer to the current Object that the key has to be in |
| 121 | // This will throw if the value is not an Object |
| 122 | const json_spirit::mObject* curObj = curVal ? &curVal->get_obj() : pObj; |
| 123 | |
| 124 | // Make sure key exists, if not then return false |
| 125 | if (!curObj->count(key)) |
| 126 | return false; |