xbmc
JSONUtils.h
1 /*
2  * Copyright (C) 2005-2018 Team Kodi
3  * This file is part of Kodi - https://kodi.tv
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  * See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "JSONRPCUtils.h"
12 #include "playlists/SmartPlayList.h"
13 #include "utils/JSONVariantParser.h"
14 #include "utils/JSONVariantWriter.h"
15 #include "utils/SortUtils.h"
16 #include "utils/StringUtils.h"
17 #include "utils/Variant.h"
18 
19 #include <stdlib.h>
20 #include <string.h>
21 #include <vector>
22 
23 class CDateTime;
24 
25 namespace JSONRPC
26 {
30  enum JSONSchemaType
31  {
32  NullValue = 0x01,
33  StringValue = 0x02,
34  NumberValue = 0x04,
35  IntegerValue = 0x08,
36  BooleanValue = 0x10,
37  ArrayValue = 0x20,
38  ObjectValue = 0x40,
39  AnyValue = 0x80
40  };
41 
46  class CJSONUtils
47  {
48  public:
49  static void MillisecondsToTimeObject(int time, CVariant &result)
50  {
51  int ms = time % 1000;
52  result["milliseconds"] = ms;
53  time = (time - ms) / 1000;
54 
55  int s = time % 60;
56  result["seconds"] = s;
57  time = (time - s) / 60;
58 
59  int m = time % 60;
60  result["minutes"] = m;
61  time = (time -m) / 60;
62 
63  result["hours"] = time;
64  }
65 
66  protected:
67  static void HandleLimits(const CVariant &parameterObject, CVariant &result, int size, int &start, int &end)
68  {
69  if (size < 0)
70  size = 0;
71 
72  start = (int)parameterObject["limits"]["start"].asInteger();
73  end = (int)parameterObject["limits"]["end"].asInteger();
74  end = (end <= 0 || end > size) ? size : end;
75  start = start > end ? end : start;
76 
77  result["limits"]["start"] = start;
78  result["limits"]["end"] = end;
79  result["limits"]["total"] = size;
80  }
81 
82  static bool ParseSorting(const CVariant &parameterObject, SortBy &sortBy, SortOrder &sortOrder, SortAttribute &sortAttributes)
83  {
84  std::string method = parameterObject["sort"]["method"].asString();
85  std::string order = parameterObject["sort"]["order"].asString();
86  StringUtils::ToLower(method);
87  StringUtils::ToLower(order);
88 
89  // parse the sort attributes
90  sortAttributes = SortAttributeNone;
91  if (parameterObject["sort"]["ignorearticle"].asBoolean())
92  sortAttributes = static_cast<SortAttribute>(sortAttributes | SortAttributeIgnoreArticle);
93  if (parameterObject["sort"]["useartistsortname"].asBoolean())
94  sortAttributes = static_cast<SortAttribute>(sortAttributes | SortAttributeUseArtistSortName);
95 
96  // parse the sort order
97  sortOrder = SortUtils::SortOrderFromString(order);
98  if (sortOrder == SortOrderNone)
99  return false;
100 
101  // parse the sort method
102  sortBy = SortUtils::SortMethodFromString(method);
103 
104  return true;
105  }
106 
107  static void ParseLimits(const CVariant &parameterObject, int &limitStart, int &limitEnd)
108  {
109  limitStart = (int)parameterObject["limits"]["start"].asInteger();
110  limitEnd = (int)parameterObject["limits"]["end"].asInteger();
111  }
112 
124  static inline bool ParameterExists(const CVariant& parameterObject,
125  const std::string& key,
126  unsigned int position)
127  {
128  return IsValueMember(parameterObject, key) ||
129  (parameterObject.isArray() && parameterObject.size() > position);
130  }
131 
140  static inline bool IsValueMember(const CVariant& value, const std::string& key)
141  {
142  return value.isMember(key);
143  }
144 
157  static inline CVariant GetParameter(const CVariant& parameterObject,
158  const std::string& key,
159  unsigned int position)
160  {
161  return IsValueMember(parameterObject, key) ? parameterObject[key] : parameterObject[position];
162  }
163 
179  static inline CVariant GetParameter(const CVariant& parameterObject,
180  const std::string& key,
181  unsigned int position,
182  const CVariant& fallback)
183  {
184  return IsValueMember(parameterObject, key)
185  ? parameterObject[key]
186  : ((parameterObject.isArray() && parameterObject.size() > position)
187  ? parameterObject[position]
188  : fallback);
189  }
190 
198  static inline std::string GetString(const CVariant &value, const char* defaultValue)
199  {
200  std::string str = defaultValue;
201  if (value.isString())
202  {
203  str = value.asString();
204  }
205 
206  return str;
207  }
208 
215  static inline TransportLayerCapability StringToTransportLayer(const std::string& transport)
216  {
217  if (transport.compare("Announcing") == 0)
218  return Announcing;
219  if (transport.compare("FileDownloadDirect") == 0)
220  return FileDownloadDirect;
221  if (transport.compare("FileDownloadRedirect") == 0)
222  return FileDownloadRedirect;
223 
224  return Response;
225  }
226 
233  static inline JSONSchemaType StringToSchemaValueType(const std::string& valueType)
234  {
235  if (valueType.compare("null") == 0)
236  return NullValue;
237  if (valueType.compare("string") == 0)
238  return StringValue;
239  if (valueType.compare("number") == 0)
240  return NumberValue;
241  if (valueType.compare("integer") == 0)
242  return IntegerValue;
243  if (valueType.compare("boolean") == 0)
244  return BooleanValue;
245  if (valueType.compare("array") == 0)
246  return ArrayValue;
247  if (valueType.compare("object") == 0)
248  return ObjectValue;
249 
250  return AnyValue;
251  }
252 
259  static inline std::string SchemaValueTypeToString(JSONSchemaType valueType)
260  {
261  std::vector<JSONSchemaType> types = std::vector<JSONSchemaType>();
262  for (unsigned int value = 0x01; value <= (unsigned int)AnyValue; value *= 2)
263  {
264  if (HasType(valueType, (JSONSchemaType)value))
265  types.push_back((JSONSchemaType)value);
266  }
267 
268  std::string strType;
269  if (types.size() > 1)
270  strType.append("[");
271 
272  for (unsigned int index = 0; index < types.size(); index++)
273  {
274  if (index > 0)
275  strType.append(", ");
276 
277  switch (types.at(index))
278  {
279  case StringValue:
280  strType.append("string");
281  break;
282  case NumberValue:
283  strType.append("number");
284  break;
285  case IntegerValue:
286  strType.append("integer");
287  break;
288  case BooleanValue:
289  strType.append("boolean");
290  break;
291  case ArrayValue:
292  strType.append("array");
293  break;
294  case ObjectValue:
295  strType.append("object");
296  break;
297  case AnyValue:
298  strType.append("any");
299  break;
300  case NullValue:
301  strType.append("null");
302  break;
303  default:
304  strType.append("unknown");
305  }
306  }
307 
308  if (types.size() > 1)
309  strType.append("]");
310 
311  return strType;
312  }
313 
320  static inline void SchemaValueTypeToJson(JSONSchemaType valueType, CVariant &jsonObject)
321  {
322  jsonObject = CVariant(CVariant::VariantTypeArray);
323  for (unsigned int value = 0x01; value <= (unsigned int)AnyValue; value *= 2)
324  {
325  if (HasType(valueType, (JSONSchemaType)value))
326  jsonObject.append(SchemaValueTypeToString((JSONSchemaType)value));
327  }
328 
329  if (jsonObject.size() == 1)
330  {
331  CVariant jsonType = jsonObject[0];
332  jsonObject = jsonType;
333  }
334  }
335 
336  static inline const char *ValueTypeToString(CVariant::VariantType valueType)
337  {
338  switch (valueType)
339  {
340  case CVariant::VariantTypeString:
341  return "string";
342  case CVariant::VariantTypeDouble:
343  return "number";
344  case CVariant::VariantTypeInteger:
345  case CVariant::VariantTypeUnsignedInteger:
346  return "integer";
347  case CVariant::VariantTypeBoolean:
348  return "boolean";
349  case CVariant::VariantTypeArray:
350  return "array";
351  case CVariant::VariantTypeObject:
352  return "object";
353  case CVariant::VariantTypeNull:
354  case CVariant::VariantTypeConstNull:
355  return "null";
356  default:
357  return "unknown";
358  }
359  }
360 
370  static inline bool IsParameterType(const CVariant &parameterObject, const char *key, unsigned int position, JSONSchemaType valueType)
371  {
372  if ((valueType & AnyValue) == AnyValue)
373  return true;
374 
375  CVariant parameter;
376  if (IsValueMember(parameterObject, key))
377  parameter = parameterObject[key];
378  else if(parameterObject.isArray() && parameterObject.size() > position)
379  parameter = parameterObject[position];
380 
381  return IsType(parameter, valueType);
382  }
383 
390  static inline bool IsType(const CVariant &value, JSONSchemaType valueType)
391  {
392  if (HasType(valueType, AnyValue))
393  return true;
394  if (HasType(valueType, StringValue) && value.isString())
395  return true;
396  if (HasType(valueType, NumberValue) && (value.isInteger() || value.isUnsignedInteger() || value.isDouble()))
397  return true;
398  if (HasType(valueType, IntegerValue) && (value.isInteger() || value.isUnsignedInteger()))
399  return true;
400  if (HasType(valueType, BooleanValue) && value.isBoolean())
401  return true;
402  if (HasType(valueType, ArrayValue) && value.isArray())
403  return true;
404  if (HasType(valueType, ObjectValue) && value.isObject())
405  return true;
406 
407  return value.isNull();
408  }
409 
416  static inline void SetDefaultValue(CVariant &value, JSONSchemaType valueType)
417  {
418  switch (valueType)
419  {
420  case StringValue:
421  value = CVariant("");
422  break;
423  case NumberValue:
424  value = CVariant(CVariant::VariantTypeDouble);
425  break;
426  case IntegerValue:
427  value = CVariant(CVariant::VariantTypeInteger);
428  break;
429  case BooleanValue:
430  value = CVariant(CVariant::VariantTypeBoolean);
431  break;
432  case ArrayValue:
433  value = CVariant(CVariant::VariantTypeArray);
434  break;
435  case ObjectValue:
436  value = CVariant(CVariant::VariantTypeObject);
437  break;
438  default:
439  value = CVariant(CVariant::VariantTypeNull);
440  }
441  }
442 
443  static inline bool HasType(JSONSchemaType typeObject, JSONSchemaType type) { return (typeObject & type) == type; }
444 
445  static inline bool ParameterNotNull(const CVariant& parameterObject, const std::string& key)
446  {
447  return parameterObject.isMember(key) && !parameterObject[key].isNull();
448  }
449 
456  static void CopyStringArray(const CVariant &jsonStringArray, std::vector<std::string> &stringArray)
457  {
458  if (!jsonStringArray.isArray())
459  return;
460 
461  stringArray.clear();
462  for (CVariant::const_iterator_array it = jsonStringArray.begin_array(); it != jsonStringArray.end_array(); ++it)
463  stringArray.push_back(it->asString());
464  }
465 
466  static void SetFromDBDate(const CVariant& jsonDate, CDateTime& date);
467 
468  static void SetFromDBDateTime(const CVariant& jsonDate, CDateTime& date);
469 
470  static bool GetXspFiltering(const std::string &type, const CVariant &filter, std::string &xsp)
471  {
472  if (type.empty() || !filter.isObject())
473  return false;
474 
475  CVariant xspObj(CVariant::VariantTypeObject);
476  xspObj["type"] = type;
477 
478  if (filter.isMember("field"))
479  {
480  xspObj["rules"]["and"] = CVariant(CVariant::VariantTypeArray);
481  xspObj["rules"]["and"].push_back(filter);
482  }
483  else
484  xspObj["rules"] = filter;
485 
486  CSmartPlaylist playlist;
487  return playlist.Load(xspObj) && playlist.SaveAsJson(xsp, false);
488  }
489  };
490 }
static TransportLayerCapability StringToTransportLayer(const std::string &transport)
Returns a TransportLayerCapability value of the given string representation.
Definition: JSONUtils.h:215
static CVariant GetParameter(const CVariant &parameterObject, const std::string &key, unsigned int position, const CVariant &fallback)
Returns the json value of a parameter or the given default value.
Definition: JSONUtils.h:179
static void CopyStringArray(const CVariant &jsonStringArray, std::vector< std::string > &stringArray)
Copies the values from the jsonStringArray to the stringArray. stringArray is cleared.
Definition: JSONUtils.h:456
Definition: AddonsOperations.h:23
static void SetDefaultValue(CVariant &value, JSONSchemaType valueType)
Sets the value of the given json value to the default value of the given type.
Definition: JSONUtils.h:416
static void SchemaValueTypeToJson(JSONSchemaType valueType, CVariant &jsonObject)
Converts the given json schema type into a json object.
Definition: JSONUtils.h:320
Definition: Variant.h:29
static std::string SchemaValueTypeToString(JSONSchemaType valueType)
Returns a string representation for the given JSONSchemaType.
Definition: JSONUtils.h:259
static bool IsParameterType(const CVariant &parameterObject, const char *key, unsigned int position, JSONSchemaType valueType)
Checks if the parameter with the given name or at the given position is of a certain type...
Definition: JSONUtils.h:370
DateTime class, which uses FileTime as it&#39;s base.
Definition: XBDateTime.h:63
SortBy
Definition: SortUtils.h:49
static JSONSchemaType StringToSchemaValueType(const std::string &valueType)
Returns a JSONSchemaType value for the given string representation.
Definition: JSONUtils.h:233
static std::string GetString(const CVariant &value, const char *defaultValue)
Returns the given json value as a string.
Definition: JSONUtils.h:198
Definition: SmartPlayList.h:90
static bool IsType(const CVariant &value, JSONSchemaType valueType)
Checks if the given json value is of the given type.
Definition: JSONUtils.h:390
Helper class containing utility methods to handle json rpc method calls.
Definition: JSONUtils.h:46
static bool ParameterExists(const CVariant &parameterObject, const std::string &key, unsigned int position)
Checks if the given object contains a parameter.
Definition: JSONUtils.h:124
static CVariant GetParameter(const CVariant &parameterObject, const std::string &key, unsigned int position)
Returns the json value of a parameter.
Definition: JSONUtils.h:157
static bool IsValueMember(const CVariant &value, const std::string &key)
Checks if the given object contains a value with the given key.
Definition: JSONUtils.h:140