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)