40 static QString sanitizeString(QString str)
42 str.replace(QLatin1String(
"\\"), QLatin1String(
"\\\\"));
43 str.replace(QLatin1String(
"\""), QLatin1String(
"\\\""));
44 str.replace(QLatin1String(
"\b"), QLatin1String(
"\\b"));
45 str.replace(QLatin1String(
"\f"), QLatin1String(
"\\f"));
46 str.replace(QLatin1String(
"\n"), QLatin1String(
"\\n"));
47 str.replace(QLatin1String(
"\r"), QLatin1String(
"\\r"));
48 str.replace(QLatin1String(
"\t"), QLatin1String(
"\\t"));
49 return QString(QLatin1String(
"\"%1\"")).arg(str);
52 static QByteArray join(
const QList<QByteArray> &list,
const QByteArray &sep)
55 Q_FOREACH(
const QByteArray &i, list)
83 if(!json.isNull() || !json.isEmpty())
90 QVariant value = Json::parseValue(data, index, success);
117 else if((data.type() == QVariant::List) || (data.type() == QVariant::StringList))
119 QList<QByteArray> values;
120 const QVariantList list = data.toList();
121 Q_FOREACH(
const QVariant& v, list)
123 QByteArray serializedValue =
serialize(v);
124 if(serializedValue.isNull())
129 values << serializedValue;
132 str =
"[ " + join( values,
", " ) +
" ]";
134 else if(data.type() == QVariant::Map)
136 const QVariantMap vmap = data.toMap();
137 QMapIterator<QString, QVariant> it( vmap );
139 QList<QByteArray> pairs;
143 QByteArray serializedValue =
serialize(it.value());
144 if(serializedValue.isNull())
149 pairs << sanitizeString(it.key()).toUtf8() +
" : " + serializedValue;
151 str += join(pairs,
", ");
154 else if((data.type() == QVariant::String) || (data.type() == QVariant::ByteArray))
156 str = sanitizeString(data.toString()).toUtf8();
158 else if(data.type() == QVariant::Double)
160 str = QByteArray::number(data.toDouble(),
'g', 20);
161 if(!str.contains(
".") && ! str.contains(
"e"))
166 else if (data.type() == QVariant::Bool)
168 str = data.toBool() ?
"true" :
"false";
170 else if (data.type() == QVariant::ULongLong)
172 str = QByteArray::number(data.value<qulonglong>());
174 else if ( data.canConvert<qlonglong>() )
176 str = QByteArray::number(data.value<qlonglong>());
178 else if (data.canConvert<
long>())
180 str = QString::number(data.value<
long>()).toUtf8();
182 else if (data.canConvert<QString>())
185 str = sanitizeString(data.toString()).toUtf8();
204 QVariant Json::parseValue(
const QString &json,
int &index,
bool &success)
208 switch(Json::lookAhead(json, index))
210 case JsonTokenString:
211 return Json::parseString(json, index, success);
212 case JsonTokenNumber:
213 return Json::parseNumber(json, index);
214 case JsonTokenCurlyOpen:
215 return Json::parseObject(json, index, success);
216 case JsonTokenSquaredOpen:
217 return Json::parseArray(json, index, success);
219 Json::nextToken(json, index);
220 return QVariant(
true);
222 Json::nextToken(json, index);
223 return QVariant(
false);
225 Json::nextToken(json, index);
239 QVariant Json::parseObject(
const QString &json,
int &index,
bool &success)
245 Json::nextToken(json, index);
252 token = Json::lookAhead(json, index);
254 if(token == JsonTokenNone)
257 return QVariantMap();
259 else if(token == JsonTokenComma)
261 Json::nextToken(json, index);
263 else if(token == JsonTokenCurlyClose)
265 Json::nextToken(json, index);
271 QString name = Json::parseString(json, index, success).toString();
275 return QVariantMap();
279 token = Json::nextToken(json, index);
283 if(token != JsonTokenColon)
286 return QVariant(QVariantMap());
290 QVariant value = Json::parseValue(json, index, success);
294 return QVariantMap();
303 return QVariant(map);
309 QVariant Json::parseArray(
const QString &json,
int &index,
bool &success)
313 Json::nextToken(json, index);
318 int token = Json::lookAhead(json, index);
320 if(token == JsonTokenNone)
323 return QVariantList();
325 else if(token == JsonTokenComma)
327 Json::nextToken(json, index);
329 else if(token == JsonTokenSquaredClose)
331 Json::nextToken(json, index);
336 QVariant value = Json::parseValue(json, index, success);
340 return QVariantList();
343 list.push_back(value);
347 return QVariant(list);
353 QVariant Json::parseString(
const QString &json,
int &index,
bool &success)
358 Json::eatWhitespace(json, index);
362 bool complete =
false;
365 if(index == json.size())
379 if(index == json.size())
420 int remainingLength = json.size() - index;
422 if(remainingLength >= 4)
424 QString unicodeStr = json.mid(index, 4);
426 int symbol = unicodeStr.toInt(0, 16);
428 s.append(QChar(symbol));
450 s = QString::fromUtf8(s.toUtf8());
458 QVariant Json::parseNumber(
const QString &json,
int &index)
460 Json::eatWhitespace(json, index);
462 int lastIndex = Json::lastIndexOfNumber(json, index);
463 int charLength = (lastIndex - index) + 1;
466 numberStr = json.mid(index, charLength);
468 index = lastIndex + 1;
470 if (numberStr.contains(
'.')) {
471 return QVariant(numberStr.toDouble(NULL));
472 }
else if (numberStr.startsWith(
'-')) {
473 return QVariant(numberStr.toLongLong(NULL));
475 return QVariant(numberStr.toULongLong(NULL));
482 int Json::lastIndexOfNumber(
const QString &json,
int index)
486 for(lastIndex = index; lastIndex < json.size(); lastIndex++)
488 if(QString(
"0123456789+-.eE").indexOf(json[lastIndex]) == -1)
500 void Json::eatWhitespace(
const QString &json,
int &index)
502 for(; index < json.size(); index++)
504 if(QString(
" \t\n\r").indexOf(json[index]) == -1)
514 int Json::lookAhead(
const QString &json,
int index)
516 int saveIndex = index;
517 return Json::nextToken(json, saveIndex);
523 int Json::nextToken(
const QString &json,
int &index)
525 Json::eatWhitespace(json, index);
527 if(index == json.size())
529 return JsonTokenNone;
532 QChar c = json[index];
536 case '{':
return JsonTokenCurlyOpen;
537 case '}':
return JsonTokenCurlyClose;
538 case '[':
return JsonTokenSquaredOpen;
539 case ']':
return JsonTokenSquaredClose;
540 case ',':
return JsonTokenComma;
541 case '"':
return JsonTokenString;
542 case '0':
case '1':
case '2':
case '3':
case '4':
543 case '5':
case '6':
case '7':
case '8':
case '9':
544 case '-':
return JsonTokenNumber;
545 case ':':
return JsonTokenColon;
550 int remainingLength = json.size() - index;
553 if(remainingLength >= 4)
555 if (json[index] ==
't' && json[index + 1] ==
'r' &&
556 json[index + 2] ==
'u' && json[index + 3] ==
'e')
559 return JsonTokenTrue;
564 if (remainingLength >= 5)
566 if (json[index] ==
'f' && json[index + 1] ==
'a' &&
567 json[index + 2] ==
'l' && json[index + 3] ==
's' &&
568 json[index + 4] ==
'e')
571 return JsonTokenFalse;
576 if (remainingLength >= 4)
578 if (json[index] ==
'n' && json[index + 1] ==
'u' &&
579 json[index + 2] ==
'l' && json[index + 3] ==
'l')
582 return JsonTokenNull;
586 return JsonTokenNone;
static QVariant parse(const QString &json)
static QByteArray serialize(const QVariant &data)