2 * Copyright (c) 2014-present, Facebook, Inc.
5 * This source code is licensed in accordance with the terms specified in
6 * the LICENSE file found in the root directory of this source tree.
13 #include <osquery/utils/only_movable.h>
14 #include <osquery/utils/status/status.h>
15 #include <osquery/utils/system/system.h>
18 #pragma warning(push, 3)
19 #pragma warning(disable : 4715)
22 #include <rapidjson/document.h>
23 #include <rapidjson/error/en.h>
24 #include <rapidjson/stringbuffer.h>
25 #include <rapidjson/writer.h>
33 * @brief This provides a small wrapper around constructing JSON objects.
35 * Constructing RapidJSON objects can be slightly tricky. In our original
36 * refactoring we found several opportunities to leak memory and cause faults.
37 * This was mostly causes by setting allocators incorrectly.
39 class JSON : private only_movable {
41 explicit JSON(rapidjson::Type type);
45 JSON(JSON&&) = default;
46 JSON& operator=(JSON&&) = default;
48 /// Create a JSON wrapper for an Object (map).
49 static JSON newObject();
51 /// Create a JSON wrapper for an Array (list).
52 static JSON newArray();
54 /// Create a JSON wrapper from an existing value.
55 static JSON newFromValue(const rapidjson::Value& value);
58 /// Make a JSON object (map).
59 rapidjson::Document getObject() const;
61 /// Make a JSON array (list).
62 rapidjson::Document getArray() const;
64 /// Add a JSON object or array to a list.
65 void push(rapidjson::Value& value);
67 /// Add a JSON object or array to a list.
68 void push(rapidjson::Value& value, rapidjson::Value& arr);
70 /// Add a size_t to a JSON array.
71 void push(size_t value);
73 /// Add a size_t to a JSON array.
74 void push(size_t value, rapidjson::Value& arr);
76 /// Add a copy of a string to a JSON array.
77 void pushCopy(const std::string& value);
79 /// Add a reference to a string to a JSON array.
80 void pushCopy(const std::string& value, rapidjson::Value& arr);
83 * @brief Add a string value to a JSON object by copying the contents.
85 * This will add the key and value to an input document. If the key exists
86 * the value will be replaced.
87 * The input document must be an object type.
89 void addCopy(const std::string& key,
90 const std::string& value,
91 rapidjson::Value& obj);
94 * @brief Add a string value to a JSON object by copying the contents.
96 * This will add the key and value to the JSON document. If the key exists
97 * the value will be replaced.
98 * The document must be an object type.
100 void addCopy(const std::string& key, const std::string& value);
103 * @brief Add a string value to a JSON object by referencing the contents.
105 * The string value must live longer than the document's use.
107 * This will add the key and value to an input document. If the key exists
108 * the value will be replaced.
109 * The input document must be an object type.
111 void addRef(const std::string& key,
112 const std::string& value,
113 rapidjson::Value& obj);
116 * @brief Add a string value to a JSON object by referencing the contents.
118 * The string value must live longer than the document's use.
120 * This will add the key and value to the JSON document. If the key exists
121 * the value will be replaced.
122 * The input document must be an object type.
124 void addRef(const std::string& key, const std::string& value);
127 * @brief Add a string value to a JSON object by copying the contents.
129 * This is basically and alias for addCopy()
131 * This will add the key and value to an input document. If the key exists
132 * the value will be replaced.
133 * The input document must be an object type.
135 void add(const std::string& key,
136 const std::string& value,
137 rapidjson::Value& obj);
140 * @brief Add a string value to a JSON object by copying the contents.
142 * This is basically and alias for addCopy().
144 * This will add the key and value to the JSON document. If the key exists
145 * the value will be replaced.
146 * The document must be an object type.
148 void add(const std::string& key, const std::string& value);
151 * @brief Add a char* value to a JSON object by copying the contents.
153 * This will add the key and value to an input document. If the key exists
154 * the value will be replaced.
155 * The input document must be an object type.
157 void add(const std::string& key, const char* value, rapidjson::Value& obj);
160 * @brief Add a char* value to a JSON object by copying the contents.
162 * This will add the key and value to the JSON document. If the key exists
163 * the value will be replaced.
164 * The document must be an object type.
166 void add(const std::string& key, const char* value);
169 * @brief Add a int value to a JSON object by copying the contents.
171 * This will add the key and value to an input document. If the key exists
172 * the value will be replaced.
173 * The input document must be an object type.
175 void add(const std::string& key, int value, rapidjson::Value& obj);
178 * @brief Add a int value to a JSON object by copying the contents.
180 * This will add the key and value to the JSON document. If the key exists
181 * the value will be replaced.
182 * The document must be an object type.
184 void add(const std::string& key, int value);
187 * @brief Add a long value to a JSON object by copying the contents.
189 * This will add the key and value to an input document. If the key exists
190 * the value will be replaced.
191 * The input document must be an object type.
193 void add(const std::string& key, long value, rapidjson::Value& obj);
196 * @brief Add a long value to a JSON object by copying the contents.
198 * This will add the key and value to the JSON document. If the key exists
199 * the value will be replaced.
200 * The document must be an object type.
202 void add(const std::string& key, long value);
205 * @brief Add a long long to a JSON object by copying the
208 * This will add the key and value to an input document. If the key exists
209 * the value will be replaced.
210 * The input document must be an object type.
212 void add(const std::string& key, long long value, rapidjson::Value& obj);
214 * @brief Add a long long to a JSON object by copying the
217 * This will add the key and value to the JSON document. If the key exists
218 * the value will be replaced.
219 * The document must be an object type.
221 void add(const std::string& key, long long value);
224 * @brief Add an unsigned int value to a JSON object by copying the contents.
226 * This will add the key and value to an input document. If the key exists
227 * the value will be replaced.
228 * The input document must be an object type.
230 void add(const std::string& key, unsigned int value, rapidjson::Value& obj);
233 * @brief Add an unsigned int value to a JSON object by copying the contents.
235 * This will add the key and value to the JSON document. If the key exists
236 * the value will be replaced.
237 * The document must be an object type.
239 void add(const std::string& key, unsigned int value);
242 * @brief Add an unsigned long value to a JSON object by copying the contents.
244 * This will add the key and value to an input document. If the key exists
245 * the value will be replaced.
246 * The input document must be an object type.
248 void add(const std::string& key, unsigned long value, rapidjson::Value& obj);
251 * @brief Add an unsigned long value to a JSON object by copying the contents.
253 * This will add the key and value to the JSON document. If the key exists
254 * the value will be replaced.
255 * The document must be an object type.
257 void add(const std::string& key, unsigned long value);
260 * @brief Add an unsigned long long to a JSON object by copying the
263 * This will add the key and value to an input document. If the key exists
264 * the value will be replaced.
265 * The input document must be an object type.
267 void add(const std::string& key,
268 unsigned long long value,
269 rapidjson::Value& obj);
271 * @brief Add an unsigned long long to a JSON object by copying the
274 * This will add the key and value to the JSON document. If the key exists
275 * the value will be replaced.
276 * The document must be an object type.
278 void add(const std::string& key, unsigned long long value);
281 * @brief Add a double value to a JSON object by copying the contents.
283 * This will add the key and value to an input document. If the key exists
284 * the value will be replaced.
285 * The input document must be an object type.
287 void add(const std::string& key, double value, rapidjson::Value& obj);
289 * @brief Add an double value to a JSON object by copying the contents.
291 * This will add the key and value to the JSON document. If the key exists
292 * the value will be replaced.
293 * The document must be an object type.
295 void add(const std::string& key, double value);
298 * @brief Add a bool value to a JSON object by copying the contents.
300 * This will add the key and value to an input document. If the key exists
301 * the value will be replaced.
302 * The input document must be an object type.
304 void add(const std::string& key, bool value, rapidjson::Value& obj);
307 * @brief Add a bool value to a JSON object by copying the contents.
309 * This will add the key and value to the JSON document. If the key exists
310 * the value will be replaced.
311 * The document must be an object type.
313 void add(const std::string& key, bool value);
315 /// Add a JSON document as a member.
316 void add(const std::string& key, const rapidjson::Value& value);
318 /// Add a JSON document as a member of another document.
319 void add(const std::string& key,
320 const rapidjson::Value& value,
321 rapidjson::Value& obj);
324 * @brief Copy a JSON object/array into the document.
326 * The type of the base document may change, be careful.
328 void copyFrom(const rapidjson::Value& value, rapidjson::Value& target);
331 * @brief Copy a JSON object/array into the document.
333 * The type of the base document may change, be careful.
335 void copyFrom(const rapidjson::Value& value);
337 /// Convert this document to a JSON string.
338 Status toString(std::string& str) const;
340 /// Helper to convert a string into JSON.
341 Status fromString(const std::string& str);
343 /// Merge members of source into target, must both be objects.
344 void mergeObject(rapidjson::Value& target_obj, rapidjson::Value& source_obj);
346 void mergeArray(rapidjson::Value& target_arr, rapidjson::Value& source_arr);
348 /// Access the internal document containing the allocator.
349 rapidjson::Document& doc();
351 /// Access the internal document containing the allocator.
352 const rapidjson::Document& doc() const;
355 /// Get the value as a 'size' or 0.
356 static size_t valueToSize(const rapidjson::Value& value);
358 /// Get the value as a 'bool' or false.
359 static bool valueToBool(const rapidjson::Value& value);
362 rapidjson::Document doc_;
363 decltype(rapidjson::kObjectType) type_;
365 } // namespace osquery