swift
json.cpp
1 // SPDX-FileCopyrightText: Copyright (C) 2014 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
4 #include "misc/json.h"
5 
6 #include <QDateTime>
7 #include <QJsonDocument>
8 #include <QStringList>
9 
10 #include "misc/imageutils.h"
11 #include "misc/jsonexception.h"
12 #include "misc/stringutils.h"
13 
14 using namespace swift::misc;
15 
16 class QPixmap;
17 
18 const QJsonValue &operator>>(const QJsonValue &json, int &value)
19 {
20  value = json.toInt();
21  return json;
22 }
23 
24 const QJsonValue &operator>>(const QJsonValue &json, qlonglong &value)
25 {
26  value = static_cast<qlonglong>(json.toDouble());
27  return json;
28 }
29 
30 const QJsonValue &operator>>(const QJsonValue &json, qulonglong &value)
31 {
32  value = static_cast<qulonglong>(json.toDouble());
33  return json;
34 }
35 
36 const QJsonValue &operator>>(const QJsonValue &json, uint &value)
37 {
38  value = static_cast<uint>(json.toInt());
39  return json;
40 }
41 
42 const QJsonValue &operator>>(const QJsonValue &json, qint16 &value)
43 {
44  value = static_cast<qint16>(json.toInt());
45  return json;
46 }
47 
48 const QJsonValue &operator>>(const QJsonValue &json, QString &value)
49 {
50  value = json.toString();
51  return json;
52 }
53 
54 const QJsonValue &operator>>(const QJsonValue &json, std::string &value)
55 {
56  value = json.toString().toStdString();
57  return json;
58 }
59 
60 const QJsonValue &operator>>(const QJsonValue &json, QStringList &value)
61 {
62  for (auto &&element : json.toArray()) { value << element.toString(); }
63  return json;
64 }
65 
66 const QJsonValue &operator>>(const QJsonValue &json, double &value)
67 {
68  value = json.toDouble();
69  return json;
70 }
71 
72 const QJsonValue &operator>>(const QJsonValue &json, bool &value)
73 {
74  value = json.toBool();
75  return json;
76 }
77 
78 const QJsonValue &operator>>(const QJsonValue &json, QDateTime &value)
79 {
80  value = fromStringUtc(json.toString());
81  return json;
82 }
83 
84 const QJsonValue &operator>>(const QJsonValue &json, QPixmap &value)
85 {
86  const QString hex(json.toString());
88  return json;
89 }
90 
91 const QJsonValue &operator>>(const QJsonValue &json, QByteArray &value)
92 {
93  const QString hex(json.toString());
94  value = QByteArray::fromHex(hex.toLatin1());
95  return json;
96 }
97 
98 QJsonValueRef operator>>(QJsonValueRef json, int &value)
99 {
100  value = json.toInt();
101  return json;
102 }
103 
104 QJsonValueRef operator>>(QJsonValueRef json, qlonglong &value)
105 {
106  value = static_cast<qlonglong>(json.toDouble());
107  return json;
108 }
109 
110 QJsonValueRef operator>>(QJsonValueRef json, qulonglong &value)
111 {
112  value = static_cast<qulonglong>(json.toDouble());
113  return json;
114 }
115 
116 QJsonValueRef operator>>(QJsonValueRef json, uint &value)
117 {
118  value = static_cast<uint>(json.toInt());
119  return json;
120 }
121 
122 QJsonValueRef operator>>(QJsonValueRef json, qint16 &value)
123 {
124  value = static_cast<qint16>(json.toInt());
125  return json;
126 }
127 
128 QJsonValueRef operator>>(QJsonValueRef json, QString &value)
129 {
130  value = json.toString();
131  return json;
132 }
133 
134 QJsonValueRef operator>>(QJsonValueRef json, std::string &value)
135 {
136  value = json.toString().toStdString();
137  return json;
138 }
139 
140 QJsonValueRef operator>>(QJsonValueRef json, QStringList &value)
141 {
142  for (auto &&element : json.toArray()) { value << element.toString(); }
143  return json;
144 }
145 
146 QJsonValueRef operator>>(QJsonValueRef json, double &value)
147 {
148  value = json.toDouble();
149  return json;
150 }
151 
152 QJsonValueRef operator>>(QJsonValueRef json, bool &value)
153 {
154  value = json.toBool();
155  return json;
156 }
157 
158 QJsonValueRef operator>>(QJsonValueRef json, QDateTime &value)
159 {
160  value = fromStringUtc(json.toString());
161  return json;
162 }
163 
164 QJsonValueRef operator>>(QJsonValueRef json, QPixmap &value)
165 {
166  const QString hex(json.toString());
168  return json;
169 }
170 
171 QJsonValueRef operator>>(QJsonValueRef json, QByteArray &value)
172 {
173  const QString hex(json.toString());
174  value = QByteArray::fromHex(hex.toLatin1());
175  return json;
176 }
177 
178 QJsonArray &operator<<(QJsonArray &json, const int value)
179 {
180  json.append(QJsonValue(value));
181  return json;
182 }
183 
184 QJsonArray &operator<<(QJsonArray &json, const qint16 value)
185 {
186  json.append(QJsonValue(value));
187  return json;
188 }
189 
190 QJsonArray &operator<<(QJsonArray &json, const qlonglong value)
191 {
192  json.append(QJsonValue(value));
193  return json;
194 }
195 
196 QJsonArray &operator<<(QJsonArray &json, const uint value)
197 {
198  json.append(QJsonValue(static_cast<int>(value)));
199  return json;
200 }
201 
202 QJsonArray &operator<<(QJsonArray &json, const qulonglong value)
203 {
204  json.append(QJsonValue(static_cast<int>(value)));
205  return json;
206 }
207 
208 QJsonArray &operator<<(QJsonArray &json, const QString &value)
209 {
210  json.append(QJsonValue(value));
211  return json;
212 }
213 
214 QJsonArray &operator<<(QJsonArray &json, const std::string &value)
215 {
216  json.append(QJsonValue(QString::fromStdString(value)));
217  return json;
218 }
219 
220 QJsonArray &operator<<(QJsonArray &json, const double value)
221 {
222  json.append(QJsonValue(value));
223  return json;
224 }
225 
226 QJsonArray &operator<<(QJsonArray &json, const bool value)
227 {
228  json.append(QJsonValue(value));
229  return json;
230 }
231 
232 QJsonArray &operator<<(QJsonArray &json, const QDateTime &value)
233 {
234  json.append(QJsonValue(value.toString()));
235  return json;
236 }
237 
238 QJsonArray &operator<<(QJsonArray &json, const QPixmap &value)
239 {
240  QString pm(swift::misc::pixmapToPngHexString(value));
241  json.append(QJsonValue(pm));
242  return json;
243 }
244 
245 QJsonArray &operator<<(QJsonArray &json, const QByteArray &value)
246 {
247  QString pm(QByteArray::fromHex(value));
248  json.append(QJsonValue(pm));
249  return json;
250 }
251 
252 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const int &> &value)
253 {
254  json.insert(value.first, QJsonValue(value.second));
255  return json;
256 }
257 
258 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const qint16 &> &value)
259 {
260  json.insert(value.first, QJsonValue(value.second));
261  return json;
262 }
263 
264 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const qulonglong &> &value)
265 {
266  json.insert(value.first, QJsonValue(static_cast<int>(value.second)));
267  return json;
268 }
269 
270 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const qlonglong &> &value)
271 {
272  json.insert(value.first, QJsonValue(value.second));
273  return json;
274 }
275 
276 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const uint &> &value)
277 {
278  json.insert(value.first, QJsonValue(static_cast<int>(value.second)));
279  return json;
280 }
281 
282 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const QString &> &value)
283 {
284  json.insert(value.first, QJsonValue(value.second));
285  return json;
286 }
287 
288 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const std::string &> &value)
289 {
290  json[value.first] = QJsonValue(QString::fromStdString(value.second));
291  return json;
292 }
293 
294 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const QStringList &> &value)
295 {
296  json.insert(value.first, QJsonValue(QJsonArray::fromStringList(value.second)));
297  return json;
298 }
299 
300 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const double &> &value)
301 {
302  json.insert(value.first, QJsonValue(value.second));
303  return json;
304 }
305 
306 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const bool &> &value)
307 {
308  json.insert(value.first, QJsonValue(value.second));
309  return json;
310 }
311 
312 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const QDateTime &> &value)
313 {
314  json.insert(value.first, QJsonValue(value.second.toString()));
315  return json;
316 }
317 
318 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const QPixmap &> &value)
319 {
320  QString pm(swift::misc::pixmapToPngHexString(value.second));
321  json.insert(value.first, pm);
322  return json;
323 }
324 
325 QJsonObject &operator<<(QJsonObject &json, const std::pair<QString, const QByteArray &> &value)
326 {
327  QString pm(value.second.toHex());
328  json.insert(value.first, pm);
329  return json;
330 }
331 
332 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const int &> &value)
333 {
334  json[value.first] = QJsonValue(value.second);
335  return json;
336 }
337 
338 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const qint16 &> &value)
339 {
340  json[value.first] = QJsonValue(value.second);
341  return json;
342 }
343 
344 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const qulonglong &> &value)
345 {
346  json[value.first] = QJsonValue(static_cast<int>(value.second));
347  return json;
348 }
349 
350 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const qlonglong &> &value)
351 {
352  json[value.first] = QJsonValue(value.second);
353  return json;
354 }
355 
356 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const uint &> &value)
357 {
358  json[value.first] = QJsonValue(static_cast<int>(value.second));
359  return json;
360 }
361 
362 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const QString &> &value)
363 {
364  json[value.first] = QJsonValue(value.second);
365  return json;
366 }
367 
368 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const std::string &> &value)
369 {
370  json[value.first] = QJsonValue(QString::fromStdString(value.second));
371  return json;
372 }
373 
374 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const QStringList &> &value)
375 {
376  json[value.first] = QJsonValue(QJsonArray::fromStringList(value.second));
377  return json;
378 }
379 
380 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const double &> &value)
381 {
382  json[value.first] = QJsonValue(value.second);
383  return json;
384 }
385 
386 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const bool &> &value)
387 {
388  json[value.first] = QJsonValue(value.second);
389  return json;
390 }
391 
392 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const QDateTime &> &value)
393 {
394  json[value.first] = QJsonValue(value.second.toString());
395  return json;
396 }
397 
398 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const QPixmap &> &value)
399 {
400  QString pm(swift::misc::pixmapToPngHexString(value.second));
401  json[value.first] = pm;
402  return json;
403 }
404 
405 QJsonObject &operator<<(QJsonObject &json, const std::pair<CExplicitLatin1String, const QByteArray &> &value)
406 {
407  json[value.first] = QString(value.second.toHex());
408  return json;
409 }
410 
411 namespace swift::misc::json
412 {
413  QJsonObject jsonObjectFromString(const QString &json, bool acceptCacheFormat)
414  {
415  if (json.isEmpty()) { return QJsonObject(); }
416 
417  QJsonParseError error {};
418  const QJsonDocument jsonDoc(QJsonDocument::fromJson(json.toUtf8(), &error));
419  if (error.error != QJsonParseError::NoError) { throw CJsonException(error.errorString()); }
420 
421  return acceptCacheFormat ? json::unwrapCache(jsonDoc.object()) : jsonDoc.object();
422  }
423 
424  QString stringFromJsonObject(const QJsonObject &jsonObject, QJsonDocument::JsonFormat format)
425  {
426  const QJsonDocument doc(jsonObject);
427  const QString strJson(doc.toJson(format));
428  return strJson;
429  }
430 
431  QJsonArray jsonArrayFromString(const QString &json)
432  {
433  if (json.isEmpty()) { return QJsonArray(); }
434  const QJsonDocument jsonDoc(QJsonDocument::fromJson(json.toUtf8()));
435  return jsonDoc.array();
436  }
437 
438  QJsonObject &appendJsonObject(QJsonObject &target, const QJsonObject &toBeAppended)
439  {
440  if (toBeAppended.isEmpty()) return target;
441  const QStringList keys = toBeAppended.keys();
442  foreach (const QString &key, keys) { target.insert(key, toBeAppended.value(key)); }
443  return target;
444  }
445 
446  QJsonObject getIncrementalObject(const QJsonObject &previousObject, const QJsonObject &currentObject)
447  {
448  QJsonObject incrementalObject = currentObject;
449  for (const auto &key : previousObject.keys()) // clazy:exclude=range-loop
450  {
451  if (previousObject.value(key).isObject())
452  {
453  auto child =
454  getIncrementalObject(previousObject.value(key).toObject(), currentObject.value(key).toObject());
455  if (child.isEmpty())
456  incrementalObject.remove(key);
457  else
458  incrementalObject.insert(key, child);
459  }
460  else
461  {
462  if (currentObject.value(key) == previousObject.value(key)) incrementalObject.remove(key);
463  }
464  }
465  return incrementalObject;
466  }
467 
468  QJsonObject applyIncrementalObject(const QJsonObject &previousObject, const QJsonObject &incrementalObject)
469  {
470  QJsonObject currentObject = previousObject;
471  for (const auto &key : incrementalObject.keys()) // clazy:exclude=range-loop
472  {
473  // If it is not an object, just insert the value
474  if (!incrementalObject.value(key).isObject()) { currentObject.insert(key, incrementalObject.value(key)); }
475  else
476  {
477  auto child = applyIncrementalObject(currentObject.value(key).toObject(),
478  incrementalObject.value(key).toObject());
479  currentObject.insert(key, child);
480  }
481  }
482  return currentObject;
483  }
484 
485  bool looksLikeJson(const QString &json)
486  {
487  if (json.isEmpty()) { return false; }
488  const QString t = json.trimmed();
489  return t.startsWith('{') && t.endsWith('}');
490  }
491 
492  bool looksLikeSwiftJson(const QString &json)
493  {
494  // further checks would go here
495  return looksLikeJson(json);
496  }
497 
498  bool looksLikeSwiftDataObjectJson(const QJsonObject &object)
499  {
500  // key
501  // - type
502  // - value
503  if (object.size() != 1) { return false; }
504  const QStringList keys = object.keys();
505  if (keys.size() != 1) { return false; }
506  const QString key = keys.front();
507  const QJsonObject cacheObject = object.value(key).toObject();
508  return (cacheObject.contains("type") && cacheObject.contains("value"));
509  }
510 
511  QJsonObject swiftDataObjectValue(const QString &jsonString)
512  {
513  const QJsonObject obj = jsonObjectFromString(jsonString);
514  if (obj.isEmpty()) { return obj; }
515  return swiftDataObjectValue(obj);
516  }
517 
518  QJsonObject swiftDataObjectValue(const QJsonObject &object)
519  {
520  // key
521  // - type
522  // - value
523  if (object.size() != 1) { return object; } // no cache format
524  const QJsonObject cacheObject = object.constBegin()->toObject();
525  if (cacheObject.contains("type") && cacheObject.contains("value"))
526  {
527 #ifdef QT_DEBUG
528  const QString key = object.constBegin().key(); // clazy:exclude=unused-non-trivial-variable
529  const QString type = cacheObject.value("type").toString(); // clazy:exclude=unused-non-trivial-variable
530  Q_UNUSED(key);
531  Q_UNUSED(type);
532 #endif
533  return cacheObject.value("value").toObject();
534  }
535  return object;
536  }
537 
538  QJsonObject unwrapCache(const QJsonObject &object)
539  {
540  if (object.size() != 1) { return object; } // no cache format
541  const QJsonObject cacheObject = object.constBegin()->toObject();
542  if (cacheObject.contains("type") && cacheObject.contains("value"))
543  {
544  // return object in form type/value
545  const QString type = cacheObject.value("type").toString(); // just to verify in debugger
546  Q_UNUSED(type);
547  return cacheObject;
548  }
549  return object;
550  }
551 
552  QJsonObject unwrapCache(const QString &jsonString)
553  {
554  const QJsonObject obj = jsonObjectFromString(jsonString);
555  if (obj.isEmpty()) { return obj; }
556  return unwrapCache(obj);
557  }
558 
559  bool looksLikeSwiftContainerJson(const QJsonObject &object)
560  {
561  // CContainerbase::convertFromJson
562  return object.contains("containerbase");
563  }
564 
565  bool looksLikeSwiftTypeValuePairJson(const QJsonObject &object)
566  {
567  return (object.contains("type") && object.contains("value"));
568  }
569 
570  bool looksLikeSwiftDbJson(const QJsonObject &object) { return (object.contains("data")); }
571 
572  QString firstJsonValueAsString(const QString &json)
573  {
574  static const QString empty;
575  if (json.isEmpty()) { return empty; }
576  const QJsonObject obj = jsonObjectFromString(json);
577  return firstJsonValueAsString(obj);
578  }
579 
580  QString firstJsonValueAsString(const QJsonObject &json)
581  {
582  static const QString empty;
583  if (json.isEmpty()) { return empty; }
584  const QStringList keys1 = json.keys();
585  if (keys1.isEmpty()) { return empty; }
586  if (keys1.contains("value", Qt::CaseInsensitive)) { return json.value("value").toString(); }
587 
588  const QJsonObject jsonLevel1 = json.value(keys1.front()).toObject();
589  return jsonLevel1.value("value").toString();
590  }
591 
592  QStringList firstJsonValueAsStringList(const QString &json)
593  {
594  static const QStringList empty;
595  if (json.isEmpty()) { return empty; }
596  const QJsonObject obj = jsonObjectFromString(json);
597  return firstJsonValueAsStringList(obj);
598  }
599 
600  int firstJsonValueAsInt(const QString &json, int defaultValue, bool *ok)
601  {
602  if (ok) { *ok = false; }
603  if (json.isEmpty()) { return defaultValue; }
604  const QJsonObject obj = jsonObjectFromString(json);
605  return firstJsonValueAsInt(obj, defaultValue, ok);
606  }
607 
608  int firstJsonValueAsInt(const QJsonObject &json, int defaultValue, bool *ok)
609  {
610  if (ok) { *ok = false; }
611  if (json.isEmpty()) { return defaultValue; }
612  const QStringList keys1 = json.keys();
613  if (keys1.isEmpty()) { return defaultValue; }
614  if (keys1.contains("value", Qt::CaseInsensitive))
615  {
616  if (ok) { *ok = true; }
617  return json.value("value").toInt(defaultValue);
618  }
619 
620  const QJsonObject jsonLevel1 = json.value(keys1.front()).toObject();
621  if (!jsonLevel1.contains("value")) { return defaultValue; }
622  if (ok) { *ok = true; }
623  return jsonLevel1.value("value").toInt(defaultValue);
624  }
625 
626  QStringList firstJsonValueAsStringList(const QJsonObject &json)
627  {
628  static const QStringList empty;
629  if (json.isEmpty()) { return empty; }
630  const QStringList keys1 = json.keys();
631  if (keys1.isEmpty()) { return empty; }
632  if (keys1.contains("value", Qt::CaseInsensitive)) { return arrayToQStringList(json.value("value").toArray()); }
633 
634  const QJsonObject jsonLevel1 = json.value(keys1.front()).toObject();
635  return arrayToQStringList(jsonLevel1.value("value").toArray());
636  }
637 
638  QStringList arrayToQStringList(const QJsonArray &array)
639  {
640  QStringList sl;
641  if (array.isEmpty()) { return sl; }
642  for (int i = 0; i < array.size(); i++)
643  {
644  if (!array.at(i).isString()) { continue; }
645  sl.push_back(array.at(i).toString());
646  }
647  return sl;
648  }
649 } // namespace swift::misc::json
650 
651 QDataStream &operator<<(QDataStream &s, const std::string &v)
652 {
653  s << QString::fromStdString(v);
654  return s;
655 }
656 QDataStream &operator>>(QDataStream &s, std::string &v)
657 {
658  QString vs;
659  s >> vs;
660  v = vs.toStdString();
661  return s;
662 }
Thrown when a convertFromJson method encounters an unrecoverable error in JSON data.
Definition: jsonexception.h:24
QString stringFromJsonObject(const QJsonObject &jsonObject, QJsonDocument::JsonFormat format)
JSON Object from string.
Definition: json.cpp:424
QJsonObject & appendJsonObject(QJsonObject &target, const QJsonObject &toBeAppended)
Append to first JSON object (concatenate)
Definition: json.cpp:438
QJsonObject jsonObjectFromString(const QString &json, bool acceptCacheFormat)
JSON Object from string.
Definition: json.cpp:413
QJsonArray jsonArrayFromString(const QString &json)
JSON Array from string.
Definition: json.cpp:431
const QJsonValue & operator>>(const QJsonValue &json, int &value)
Streaming operators for QJsonValue (to value)
Definition: json.cpp:18
Free functions in swift::misc.
SWIFT_MISC_EXPORT QString pixmapToPngHexString(const QPixmap &pixmap)
Pixmap as HEX string (for PNG image)
Definition: imageutils.cpp:33
SWIFT_MISC_EXPORT bool pngHexStringToPixmapRef(const QString &hexString, QPixmap &pixmap)
Hex encoded pixmap string to Pixmap.
Definition: imageutils.cpp:48
QDebug operator<<(QDebug d, const CRange< I > &range)
Streaming operators for CRange to qDebug.
Definition: range.h:298
SWIFT_MISC_EXPORT QDateTime fromStringUtc(const QString &dateTimeString, const QString &format)
Same as QDateTime::fromString but QDateTime will be set to UTC.