qmjsontype_qmjsonobject.cpp
Go to the documentation of this file.
1 //
2 // QtMark JSON Library
3 //
4 // Copyright (C) 2015 Assured Information Security, Inc.
5 // Author: Rian Quinn <quinnr@ainfosec.com>
6 // Author: Rodney Forbes <forbesr@ainfosec.com>
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 // ============================================================================
23 // Includes
24 // ============================================================================
25 
27 
28 // ============================================================================
29 // QMJsonType<QMPointer<QMJsonObject> > Implementation
30 // ============================================================================
31 
32 template <>
33 QMPointer<QMJsonValue> QM_JSON_EXPORT QMJsonType<QMPointer<QMJsonObject> >::fromJson(const QString &json, int32_t &index)
34 {
35  auto object = QMPointer<QMJsonObject>(new QMJsonObject);
36 
37  index++;
38 
39  do
40  {
41  QMJsonValue::skipSpaces(json, index);
42  QMJsonValue::verifyIndex(json, index);
43 
44  switch(json.at(index).toLatin1())
45  {
46  case '}':
47  index++;
48  return QMPointer<QMJsonValue>(new QMJsonValue(object));
49 
50  case ',':
51  index++;
52  continue;
53 
54  default:
55  break;
56  };
57 
58  auto key = QMJsonValue::fromJson(json, index);
59 
60  if(key == NULL || key->isString() == false)
61  QMJsonValue::throwError(json, index, "Key is not a string. Key's in a JSON object must be a valid JSON string");
62 
63  QMJsonValue::skipSpaces(json, index);
64  QMJsonValue::verifyIndex(json, index);
65 
66  switch(json.at(index).toLatin1())
67  {
68  case ':':
69  index++;
70  break;
71 
72  default:
73  QMJsonValue::throwError(json, index, "Expected \":\"");
74  };
75 
76  QMJsonValue::skipSpaces(json, index);
77  QMJsonValue::verifyIndex(json, index);
78 
79  object->insert(key->toString(), QMJsonValue::fromJson(json, index));
80  }
81  while(1);
82 
83  return QMPointer<QMJsonValue>(new QMJsonValue());
84 }
85 
86 template <>
88 {
89  auto json = QString();
90  const auto &object = this->get();
91 
92  // Note: This functions is basically written with 4 different implementaions
93  // with as much code being shared as possible. Instead of trying to create
94  // a generic way of handling all of this, the following provides better
95  // optimized paths depending on what your attempting to do. If you modify
96  // one, make sure the other three are updated as well (if needed)
97 
98  if(object.isNull() == true)
99  return "{}";
100 
101  if(object->count() == 0)
102  return "{}";
103 
104  if(tab == (int32_t)QMJsonFormat_Optimized)
105  {
106  json += '{';
107 
108  switch(sort)
109  {
110  case QMJsonSort_None:
111  {
112  auto iter = object->cbegin();
113 
114  while(iter != object->cend())
115  {
116  if(iter.value().isNull() == true)
117  continue;
118 
119  json += '"';
120  json += iter.key();
121  json += "\":";
122  json += iter.value()->toJson((QMJsonFormat)tab, sort);
123  json += ',';
124 
125  iter++;
126  }
127 
128  break;
129  }
130 
131  default:
132  {
133  QStringList keys = object->keys();
134  keys.sort(convertQMJsonSort(sort));
135 
136  for(const auto &key : keys)
137  {
138  const auto &value = object->value(key);
139 
140  json += '"';
141  json += key;
142  json += "\":";
143  json += value->toJson((QMJsonFormat)tab, sort);
144  json += ',';
145  }
146  }
147  }
148 
149  return json.replace(json.length() - 1, 1, '}');
150  }
151  else
152  {
153  json += '{';
154 
155  tab += 4;
156  auto space = QString(tab, ' ');
157  switch(sort)
158  {
159  case QMJsonSort_None:
160  {
161  auto iter = object->cbegin();
162 
163  while(iter != object->cend())
164  {
165  if(iter.value().isNull() == true)
166  continue;
167 
168  json += "\r\n";
169  json += space;
170  json += '"';
171  json += iter.key();
172  json += "\":";
173  json += iter.value()->toJson((QMJsonFormat)tab, sort);
174  json += ',';
175 
176  iter++;
177  }
178 
179  break;
180  }
181 
182  default:
183  {
184  QStringList keys = object->keys();
185  keys.sort(convertQMJsonSort(sort));
186 
187  for(const auto &key : keys)
188  {
189  const auto &value = object->value(key);
190 
191  json += "\r\n";
192  json += space;
193  json += '"';
194  json += key;
195  json += "\":";
196  json += value->toJson((QMJsonFormat)tab, sort);
197  json += ',';
198  }
199  }
200  }
201  tab -= 4;
202 
203  json.remove(json.length() - 1, 1);
204  json += "\r\n";
205  json += QString(tab, ' ');
206  json += '}';
207 
208  return json;
209  }
210 }
211 
212 template <>
214 {
215  return true;
216 }
virtual QString toJson(int32_t tab, QMJsonSort sort)
Definition: qmjsontype.h:189
static QMPointer< QMJsonValue > fromJson(const QString &json)
#define QM_JSON_EXPORT
Definition: qmjsontype.h:36
QMJsonFormat
Definition: qmjsontype.h:62
static QMPointer< QMJsonValue > fromJson(const QString &json, int32_t &index)
Definition: qmjsontype.h:198
virtual bool isBaseType(void)
Definition: qmjsontype.h:213
QMJsonSort
Definition: qmjsontype.h:68
Qt::CaseSensitivity convertQMJsonSort(QMJsonSort sort)
Definition: qmjsontype.h:85