defuze.me
Client
|
00001 #include "jsonparser.hpp" 00002 #include <QDebug> 00003 00004 using namespace Network; 00005 00006 JsonParser::JsonParser() 00007 { 00008 } 00009 00010 QVariant JsonParser::parse(const QByteArray& data) const 00011 { 00012 QScriptValue value; 00013 QScriptEngine engine; 00014 value = engine.evaluate(QString("(") + QString(data) + ")"); 00015 00016 if (engine.hasUncaughtException()) 00017 return QVariant(); 00018 return partialParse(value); 00019 } 00020 00021 00022 QVariant JsonParser::partialParse(const QScriptValue& value) const 00023 { 00024 if (value.isArray()) 00025 { 00026 QScriptValueIterator it(value); 00027 QVariantList list; 00028 00029 while (it.hasNext()) 00030 { 00031 it.next(); 00032 if (!it.hasNext() && it.value().isNumber() && it.value().toInteger() == list.size()) 00033 break; 00034 list << partialParse(it.value()); 00035 } 00036 return list; 00037 } 00038 if (value.isObject()) 00039 { 00040 QScriptValueIterator it(value); 00041 QVariantMap map; 00042 00043 while (it.hasNext()) 00044 { 00045 it.next(); 00046 map[it.name()] = partialParse(it.value()); 00047 } 00048 return map; 00049 } 00050 else 00051 { 00052 return value.toVariant(); 00053 } 00054 } 00055 00056 QByteArray JsonParser::serialize(const QVariant& data) const 00057 { 00058 return partialSerialize(data, 0); 00059 } 00060 00061 QByteArray JsonParser::partialSerialize(const QVariant& value, const short spaces) const 00062 { 00063 QByteArray out; 00064 00065 if ( ! value.isValid() ) { 00066 out = "null"; 00067 } 00068 else if (value.type() == QVariant::List || value.type() == QVariant::StringList) 00069 { 00070 const QVariantList &list = value.toList(); 00071 QList<QByteArray> values; 00072 Q_FOREACH( const QVariant& var, list) 00073 { 00074 values << partialSerialize(var, spaces + 1); 00075 } 00076 out = "[\n" + indent(spaces + 1) + join( values, ",\n" + indent(spaces + 1)) + "\n" + indent(spaces) + "]"; 00077 } 00078 else if (value.type() == QVariant::Map) 00079 { 00080 QVariantMap::const_iterator it; 00081 00082 out += "{\n"; 00083 for(it = value.toMap().constBegin(); it != value.toMap().constEnd(); it++) 00084 { 00085 if (it != value.toMap().constBegin()) 00086 out += ",\n"; 00087 out += indent(spaces + 1) + sanitizeString(it.key()) + ": " + partialSerialize(it.value(), spaces + 1); 00088 } 00089 out += "\n" + indent(spaces) + "}"; 00090 } 00091 else if (value.type() == QVariant::Bool) 00092 { 00093 out = (value.toBool() ? "true" : "false"); 00094 } 00095 else if (value.type() == QVariant::String || 00096 value.type() == QVariant::DateTime || 00097 value.type() == QVariant::ByteArray) 00098 { 00099 out += sanitizeString(value.toString()); 00100 } 00101 else 00102 { 00103 out += value.toString(); 00104 } 00105 return out; 00106 } 00107 00108 QByteArray JsonParser::indent(const short spaces) const 00109 { 00110 return QByteArray(spaces * 2, ' '); 00111 } 00112 00113 00114 QByteArray JsonParser::join( const QList<QByteArray>& list, const QByteArray& sep ) const 00115 { 00116 QByteArray res; 00117 Q_FOREACH( const QByteArray& i, list ) 00118 { 00119 if ( !res.isEmpty() ) 00120 res += sep; 00121 res += i; 00122 } 00123 return res; 00124 } 00125 00126 QString JsonParser::sanitizeString(const QString& input) const 00127 { 00128 QString str = input; 00129 00130 str.replace( QLatin1String( "\\" ), QLatin1String( "\\\\" ) ); 00131 // escape unicode chars 00132 QString result; 00133 const ushort* unicode = str.utf16(); 00134 unsigned int i = 0; 00135 while ( unicode[ i ] ) { 00136 if ( unicode[ i ] < 128 ) { 00137 result.append( QChar( unicode[ i ] ) ); 00138 } 00139 else { 00140 QString hexCode = QString::number( unicode[ i ], 16 ).rightJustified( 4, QLatin1Char('0') ); 00141 result.append( QLatin1String ("\\u") ).append( hexCode ); 00142 } 00143 ++i; 00144 } 00145 str = result; 00146 str.replace( QLatin1String( "\"" ), QLatin1String( "\\\"" ) ); 00147 str.replace( QLatin1String( "\b" ), QLatin1String( "\\b" ) ); 00148 str.replace( QLatin1String( "\f" ), QLatin1String( "\\f" ) ); 00149 str.replace( QLatin1String( "\n" ), QLatin1String( "\\n" ) ); 00150 str.replace( QLatin1String( "\r" ), QLatin1String( "\\r" ) ); 00151 str.replace( QLatin1String( "\t" ), QLatin1String( "\\t" ) ); 00152 return QString( QLatin1String( "\"%1\"" ) ).arg( str ); 00153 } 00154 00155 void JsonParser::test() 00156 { 00157 JsonParser p; 00158 QVariant value; 00159 QByteArray result; 00160 const QByteArray json = 00161 "[\n" 00162 " {\n" 00163 " \"address\": {\n" 00164 " \"city\": \"New York\",\n" 00165 " \"main\": true,\n" 00166 " \"postalCode\": \"10021\",\n" 00167 " \"state\": \"NY\",\n" 00168 " \"streetAddress\": \"21 2nd Street\"\n" 00169 " },\n" 00170 " \"age\": 25,\n" 00171 " \"firstName\": \"John\",\n" 00172 " \"lastName\": \"Smith\",\n" 00173 " \"phoneNumber\": [\n" 00174 " {\n" 00175 " \"number\": \"212 555-1234\",\n" 00176 " \"type\": \"home\"\n" 00177 " },\n" 00178 " {\n" 00179 " \"number\": \"646 555-4567\",\n" 00180 " \"type\": \"fax\"\n" 00181 " }\n" 00182 " ]\n" 00183 " }\n" 00184 "]"; 00185 00186 value = p.parse(json); 00187 //qDebug() << value; 00188 result = p.serialize(value); 00189 //qDebug() << result; 00190 Q_ASSERT_X(result == json, "JsonParser::test", "serialization does not match original"); 00191 }