1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/base/json.h" 12 13 #include <errno.h> 14 #include <limits.h> 15 #include <stdlib.h> 16 17 #include <sstream> 18 19 namespace rtc { 20 21 bool GetStringFromJson(const Json::Value& in, std::string* out) { 22 if (!in.isString()) { 23 std::ostringstream s; 24 if (in.isBool()) { 25 s << std::boolalpha << in.asBool(); 26 } else if (in.isInt()) { 27 s << in.asInt(); 28 } else if (in.isUInt()) { 29 s << in.asUInt(); 30 } else if (in.isDouble()) { 31 s << in.asDouble(); 32 } else { 33 return false; 34 } 35 *out = s.str(); 36 } else { 37 *out = in.asString(); 38 } 39 return true; 40 } 41 42 bool GetIntFromJson(const Json::Value& in, int* out) { 43 bool ret; 44 if (!in.isString()) { 45 ret = in.isConvertibleTo(Json::intValue); 46 if (ret) { 47 *out = in.asInt(); 48 } 49 } else { 50 long val; // NOLINT 51 const char* c_str = in.asCString(); 52 char* end_ptr; 53 errno = 0; 54 val = strtol(c_str, &end_ptr, 10); // NOLINT 55 ret = (end_ptr != c_str && *end_ptr == '\0' && !errno && 56 val >= INT_MIN && val <= INT_MAX); 57 *out = val; 58 } 59 return ret; 60 } 61 62 bool GetUIntFromJson(const Json::Value& in, unsigned int* out) { 63 bool ret; 64 if (!in.isString()) { 65 ret = in.isConvertibleTo(Json::uintValue); 66 if (ret) { 67 *out = in.asUInt(); 68 } 69 } else { 70 unsigned long val; // NOLINT 71 const char* c_str = in.asCString(); 72 char* end_ptr; 73 errno = 0; 74 val = strtoul(c_str, &end_ptr, 10); // NOLINT 75 ret = (end_ptr != c_str && *end_ptr == '\0' && !errno && 76 val <= UINT_MAX); 77 *out = val; 78 } 79 return ret; 80 } 81 82 bool GetBoolFromJson(const Json::Value& in, bool* out) { 83 bool ret; 84 if (!in.isString()) { 85 ret = in.isConvertibleTo(Json::booleanValue); 86 if (ret) { 87 *out = in.asBool(); 88 } 89 } else { 90 if (in.asString() == "true") { 91 *out = true; 92 ret = true; 93 } else if (in.asString() == "false") { 94 *out = false; 95 ret = true; 96 } else { 97 ret = false; 98 } 99 } 100 return ret; 101 } 102 103 bool GetDoubleFromJson(const Json::Value& in, double* out) { 104 bool ret; 105 if (!in.isString()) { 106 ret = in.isConvertibleTo(Json::realValue); 107 if (ret) { 108 *out = in.asDouble(); 109 } 110 } else { 111 double val; 112 const char* c_str = in.asCString(); 113 char* end_ptr; 114 errno = 0; 115 val = strtod(c_str, &end_ptr); 116 ret = (end_ptr != c_str && *end_ptr == '\0' && !errno); 117 *out = val; 118 } 119 return ret; 120 } 121 122 namespace { 123 template<typename T> 124 bool JsonArrayToVector(const Json::Value& value, 125 bool (*getter)(const Json::Value& in, T* out), 126 std::vector<T> *vec) { 127 vec->clear(); 128 if (!value.isArray()) { 129 return false; 130 } 131 132 for (Json::Value::ArrayIndex i = 0; i < value.size(); ++i) { 133 T val; 134 if (!getter(value[i], &val)) { 135 return false; 136 } 137 vec->push_back(val); 138 } 139 140 return true; 141 } 142 // Trivial getter helper 143 bool GetValueFromJson(const Json::Value& in, Json::Value* out) { 144 *out = in; 145 return true; 146 } 147 } // unnamed namespace 148 149 bool JsonArrayToValueVector(const Json::Value& in, 150 std::vector<Json::Value>* out) { 151 return JsonArrayToVector(in, GetValueFromJson, out); 152 } 153 154 bool JsonArrayToIntVector(const Json::Value& in, 155 std::vector<int>* out) { 156 return JsonArrayToVector(in, GetIntFromJson, out); 157 } 158 159 bool JsonArrayToUIntVector(const Json::Value& in, 160 std::vector<unsigned int>* out) { 161 return JsonArrayToVector(in, GetUIntFromJson, out); 162 } 163 164 bool JsonArrayToStringVector(const Json::Value& in, 165 std::vector<std::string>* out) { 166 return JsonArrayToVector(in, GetStringFromJson, out); 167 } 168 169 bool JsonArrayToBoolVector(const Json::Value& in, 170 std::vector<bool>* out) { 171 return JsonArrayToVector(in, GetBoolFromJson, out); 172 } 173 174 bool JsonArrayToDoubleVector(const Json::Value& in, 175 std::vector<double>* out) { 176 return JsonArrayToVector(in, GetDoubleFromJson, out); 177 } 178 179 namespace { 180 template<typename T> 181 Json::Value VectorToJsonArray(const std::vector<T>& vec) { 182 Json::Value result(Json::arrayValue); 183 for (size_t i = 0; i < vec.size(); ++i) { 184 result.append(Json::Value(vec[i])); 185 } 186 return result; 187 } 188 } // unnamed namespace 189 190 Json::Value ValueVectorToJsonArray(const std::vector<Json::Value>& in) { 191 return VectorToJsonArray(in); 192 } 193 194 Json::Value IntVectorToJsonArray(const std::vector<int>& in) { 195 return VectorToJsonArray(in); 196 } 197 198 Json::Value UIntVectorToJsonArray(const std::vector<unsigned int>& in) { 199 return VectorToJsonArray(in); 200 } 201 202 Json::Value StringVectorToJsonArray(const std::vector<std::string>& in) { 203 return VectorToJsonArray(in); 204 } 205 206 Json::Value BoolVectorToJsonArray(const std::vector<bool>& in) { 207 return VectorToJsonArray(in); 208 } 209 210 Json::Value DoubleVectorToJsonArray(const std::vector<double>& in) { 211 return VectorToJsonArray(in); 212 } 213 214 bool GetValueFromJsonArray(const Json::Value& in, size_t n, 215 Json::Value* out) { 216 if (!in.isArray() || !in.isValidIndex(static_cast<int>(n))) { 217 return false; 218 } 219 220 *out = in[static_cast<Json::Value::ArrayIndex>(n)]; 221 return true; 222 } 223 224 bool GetIntFromJsonArray(const Json::Value& in, size_t n, 225 int* out) { 226 Json::Value x; 227 return GetValueFromJsonArray(in, n, &x) && GetIntFromJson(x, out); 228 } 229 230 bool GetUIntFromJsonArray(const Json::Value& in, size_t n, 231 unsigned int* out) { 232 Json::Value x; 233 return GetValueFromJsonArray(in, n, &x) && GetUIntFromJson(x, out); 234 } 235 236 bool GetStringFromJsonArray(const Json::Value& in, size_t n, 237 std::string* out) { 238 Json::Value x; 239 return GetValueFromJsonArray(in, n, &x) && GetStringFromJson(x, out); 240 } 241 242 bool GetBoolFromJsonArray(const Json::Value& in, size_t n, 243 bool* out) { 244 Json::Value x; 245 return GetValueFromJsonArray(in, n, &x) && GetBoolFromJson(x, out); 246 } 247 248 bool GetDoubleFromJsonArray(const Json::Value& in, size_t n, 249 double* out) { 250 Json::Value x; 251 return GetValueFromJsonArray(in, n, &x) && GetDoubleFromJson(x, out); 252 } 253 254 bool GetValueFromJsonObject(const Json::Value& in, const std::string& k, 255 Json::Value* out) { 256 if (!in.isObject() || !in.isMember(k)) { 257 return false; 258 } 259 260 *out = in[k]; 261 return true; 262 } 263 264 bool GetIntFromJsonObject(const Json::Value& in, const std::string& k, 265 int* out) { 266 Json::Value x; 267 return GetValueFromJsonObject(in, k, &x) && GetIntFromJson(x, out); 268 } 269 270 bool GetUIntFromJsonObject(const Json::Value& in, const std::string& k, 271 unsigned int* out) { 272 Json::Value x; 273 return GetValueFromJsonObject(in, k, &x) && GetUIntFromJson(x, out); 274 } 275 276 bool GetStringFromJsonObject(const Json::Value& in, const std::string& k, 277 std::string* out) { 278 Json::Value x; 279 return GetValueFromJsonObject(in, k, &x) && GetStringFromJson(x, out); 280 } 281 282 bool GetBoolFromJsonObject(const Json::Value& in, const std::string& k, 283 bool* out) { 284 Json::Value x; 285 return GetValueFromJsonObject(in, k, &x) && GetBoolFromJson(x, out); 286 } 287 288 bool GetDoubleFromJsonObject(const Json::Value& in, const std::string& k, 289 double* out) { 290 Json::Value x; 291 return GetValueFromJsonObject(in, k, &x) && GetDoubleFromJson(x, out); 292 } 293 294 std::string JsonValueToString(const Json::Value& json) { 295 Json::FastWriter w; 296 std::string value = w.write(json); 297 return value.substr(0, value.size() - 1); // trim trailing newline 298 } 299 300 } // namespace rtc 301