1 /* 2 * libjingle 3 * Copyright 2004--2005, Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/base/json.h" 29 30 #include <errno.h> 31 32 #include <climits> 33 #include <cstdlib> 34 #include <sstream> 35 36 bool GetStringFromJson(const Json::Value& in, std::string* out) { 37 if (!in.isString()) { 38 std::ostringstream s; 39 if (in.isBool()) { 40 s << std::boolalpha << in.asBool(); 41 } else if (in.isInt()) { 42 s << in.asInt(); 43 } else if (in.isUInt()) { 44 s << in.asUInt(); 45 } else if (in.isDouble()) { 46 s << in.asDouble(); 47 } else { 48 return false; 49 } 50 *out = s.str(); 51 } else { 52 *out = in.asString(); 53 } 54 return true; 55 } 56 57 bool GetIntFromJson(const Json::Value& in, int* out) { 58 bool ret; 59 if (!in.isString()) { 60 ret = in.isConvertibleTo(Json::intValue); 61 if (ret) { 62 *out = in.asInt(); 63 } 64 } else { 65 long val; // NOLINT 66 const char* c_str = in.asCString(); 67 char* end_ptr; 68 errno = 0; 69 val = strtol(c_str, &end_ptr, 10); // NOLINT 70 ret = (end_ptr != c_str && *end_ptr == '\0' && !errno && 71 val >= INT_MIN && val <= INT_MAX); 72 *out = val; 73 } 74 return ret; 75 } 76 77 bool GetUIntFromJson(const Json::Value& in, unsigned int* out) { 78 bool ret; 79 if (!in.isString()) { 80 ret = in.isConvertibleTo(Json::uintValue); 81 if (ret) { 82 *out = in.asUInt(); 83 } 84 } else { 85 unsigned long val; // NOLINT 86 const char* c_str = in.asCString(); 87 char* end_ptr; 88 errno = 0; 89 val = strtoul(c_str, &end_ptr, 10); // NOLINT 90 ret = (end_ptr != c_str && *end_ptr == '\0' && !errno && 91 val <= UINT_MAX); 92 *out = val; 93 } 94 return ret; 95 } 96 97 bool GetBoolFromJson(const Json::Value& in, bool* out) { 98 bool ret; 99 if (!in.isString()) { 100 ret = in.isConvertibleTo(Json::booleanValue); 101 if (ret) { 102 *out = in.asBool(); 103 } 104 } else { 105 if (in.asString() == "true") { 106 *out = true; 107 ret = true; 108 } else if (in.asString() == "false") { 109 *out = false; 110 ret = true; 111 } else { 112 ret = false; 113 } 114 } 115 return ret; 116 } 117 118 bool GetDoubleFromJson(const Json::Value& in, double* out) { 119 bool ret; 120 if (!in.isString()) { 121 ret = in.isConvertibleTo(Json::realValue); 122 if (ret) { 123 *out = in.asDouble(); 124 } 125 } else { 126 double val; 127 const char* c_str = in.asCString(); 128 char* end_ptr; 129 errno = 0; 130 val = strtod(c_str, &end_ptr); 131 ret = (end_ptr != c_str && *end_ptr == '\0' && !errno); 132 *out = val; 133 } 134 return ret; 135 } 136 137 namespace { 138 template<typename T> 139 bool JsonArrayToVector(const Json::Value& value, 140 bool (*getter)(const Json::Value& in, T* out), 141 std::vector<T> *vec) { 142 vec->clear(); 143 if (!value.isArray()) { 144 return false; 145 } 146 147 for (Json::Value::ArrayIndex i = 0; i < value.size(); ++i) { 148 T val; 149 if (!getter(value[i], &val)) { 150 return false; 151 } 152 vec->push_back(val); 153 } 154 155 return true; 156 } 157 // Trivial getter helper 158 bool GetValueFromJson(const Json::Value& in, Json::Value* out) { 159 *out = in; 160 return true; 161 } 162 } // unnamed namespace 163 164 bool JsonArrayToValueVector(const Json::Value& in, 165 std::vector<Json::Value>* out) { 166 return JsonArrayToVector(in, GetValueFromJson, out); 167 } 168 169 bool JsonArrayToIntVector(const Json::Value& in, 170 std::vector<int>* out) { 171 return JsonArrayToVector(in, GetIntFromJson, out); 172 } 173 174 bool JsonArrayToUIntVector(const Json::Value& in, 175 std::vector<unsigned int>* out) { 176 return JsonArrayToVector(in, GetUIntFromJson, out); 177 } 178 179 bool JsonArrayToStringVector(const Json::Value& in, 180 std::vector<std::string>* out) { 181 return JsonArrayToVector(in, GetStringFromJson, out); 182 } 183 184 bool JsonArrayToBoolVector(const Json::Value& in, 185 std::vector<bool>* out) { 186 return JsonArrayToVector(in, GetBoolFromJson, out); 187 } 188 189 bool JsonArrayToDoubleVector(const Json::Value& in, 190 std::vector<double>* out) { 191 return JsonArrayToVector(in, GetDoubleFromJson, out); 192 } 193 194 namespace { 195 template<typename T> 196 Json::Value VectorToJsonArray(const std::vector<T>& vec) { 197 Json::Value result(Json::arrayValue); 198 for (size_t i = 0; i < vec.size(); ++i) { 199 result.append(Json::Value(vec[i])); 200 } 201 return result; 202 } 203 } // unnamed namespace 204 205 Json::Value ValueVectorToJsonArray(const std::vector<Json::Value>& in) { 206 return VectorToJsonArray(in); 207 } 208 209 Json::Value IntVectorToJsonArray(const std::vector<int>& in) { 210 return VectorToJsonArray(in); 211 } 212 213 Json::Value UIntVectorToJsonArray(const std::vector<unsigned int>& in) { 214 return VectorToJsonArray(in); 215 } 216 217 Json::Value StringVectorToJsonArray(const std::vector<std::string>& in) { 218 return VectorToJsonArray(in); 219 } 220 221 Json::Value BoolVectorToJsonArray(const std::vector<bool>& in) { 222 return VectorToJsonArray(in); 223 } 224 225 Json::Value DoubleVectorToJsonArray(const std::vector<double>& in) { 226 return VectorToJsonArray(in); 227 } 228 229 bool GetValueFromJsonArray(const Json::Value& in, size_t n, 230 Json::Value* out) { 231 if (!in.isArray() || !in.isValidIndex(static_cast<int>(n))) { 232 return false; 233 } 234 235 *out = in[static_cast<Json::Value::ArrayIndex>(n)]; 236 return true; 237 } 238 239 bool GetIntFromJsonArray(const Json::Value& in, size_t n, 240 int* out) { 241 Json::Value x; 242 return GetValueFromJsonArray(in, n, &x) && GetIntFromJson(x, out); 243 } 244 245 bool GetUIntFromJsonArray(const Json::Value& in, size_t n, 246 unsigned int* out) { 247 Json::Value x; 248 return GetValueFromJsonArray(in, n, &x) && GetUIntFromJson(x, out); 249 } 250 251 bool GetStringFromJsonArray(const Json::Value& in, size_t n, 252 std::string* out) { 253 Json::Value x; 254 return GetValueFromJsonArray(in, n, &x) && GetStringFromJson(x, out); 255 } 256 257 bool GetBoolFromJsonArray(const Json::Value& in, size_t n, 258 bool* out) { 259 Json::Value x; 260 return GetValueFromJsonArray(in, n, &x) && GetBoolFromJson(x, out); 261 } 262 263 bool GetDoubleFromJsonArray(const Json::Value& in, size_t n, 264 double* out) { 265 Json::Value x; 266 return GetValueFromJsonArray(in, n, &x) && GetDoubleFromJson(x, out); 267 } 268 269 bool GetValueFromJsonObject(const Json::Value& in, const std::string& k, 270 Json::Value* out) { 271 if (!in.isObject() || !in.isMember(k)) { 272 return false; 273 } 274 275 *out = in[k]; 276 return true; 277 } 278 279 bool GetIntFromJsonObject(const Json::Value& in, const std::string& k, 280 int* out) { 281 Json::Value x; 282 return GetValueFromJsonObject(in, k, &x) && GetIntFromJson(x, out); 283 } 284 285 bool GetUIntFromJsonObject(const Json::Value& in, const std::string& k, 286 unsigned int* out) { 287 Json::Value x; 288 return GetValueFromJsonObject(in, k, &x) && GetUIntFromJson(x, out); 289 } 290 291 bool GetStringFromJsonObject(const Json::Value& in, const std::string& k, 292 std::string* out) { 293 Json::Value x; 294 return GetValueFromJsonObject(in, k, &x) && GetStringFromJson(x, out); 295 } 296 297 bool GetBoolFromJsonObject(const Json::Value& in, const std::string& k, 298 bool* out) { 299 Json::Value x; 300 return GetValueFromJsonObject(in, k, &x) && GetBoolFromJson(x, out); 301 } 302 303 bool GetDoubleFromJsonObject(const Json::Value& in, const std::string& k, 304 double* out) { 305 Json::Value x; 306 return GetValueFromJsonObject(in, k, &x) && GetDoubleFromJson(x, out); 307 } 308 309 std::string JsonValueToString(const Json::Value& json) { 310 Json::FastWriter w; 311 std::string value = w.write(json); 312 return value.substr(0, value.size() - 1); // trim trailing newline 313 } 314