/**************************************************************************** ** ** Copyright (c) 2010 Girish Ramakrishnan ** ** Use, modification and distribution is allowed without limitation, ** warranty, liability or support of any kind. ** ****************************************************************************/ #include "json.h" #include "jsonparser.cpp" namespace Json { QVariant parse(const QByteArray &json, QString *error) { JsonLexer lexer(json); JsonParser parser; if (!parser.parse(&lexer) && error) { *error = parser.errorMessage(); } return parser.result(); } static QByteArray escape(const QVariant &variant) { QString str = variant.toString(); QByteArray res; res.reserve(str.length()); for (int i = 0; i < str.length(); i++) { if (str[i] == '\b') { res += "\\b"; } else if (str[i] == '\f') { res += "\\f"; } else if (str[i] == '\n') { res += "\\n"; } else if (str[i] == '\r') { res += "\\r"; } else if (str[i] == '\t') { res += "\\t"; } else if (str[i] == '\"') { res += "\\\""; } else if (str[i] == '\\') { res += "\\\\"; } else if (str[i].unicode() > 127) { res += "\\u" + QString::number(str[i].unicode(), 16).rightJustified(4, '0'); } else { res += str[i].toAscii(); } } return res; } QByteArray stringify(const QVariant &variant) { QByteArray result; if (variant.type() == QVariant::List || variant.type() == QVariant::StringList) { result += "["; QVariantList list = variant.toList(); for (int i = 0; i < list.count(); i++) { if (i != 0) result += ","; result += stringify(list[i]); } result += "]"; } else if (variant.type() == QVariant::Map) { QVariantMap map = variant.toMap(); QVariantMap::const_iterator it = map.constBegin(); result += "{"; while (it != map.constEnd()) { if (it != map.constBegin()) result += ","; result += "\"" + escape(it.key()) + "\":"; result += stringify(it.value()); ++it; } result += "}"; } else if (variant.type() == QVariant::String || variant.type() == QVariant::ByteArray) { result = "\"" + escape(variant) + "\""; } else if (variant.type() == QVariant::Double || (int) variant.type() == (int) QMetaType::Float) { result.setNum(variant.toDouble(), 'g', 15); } else if (variant.type() == QVariant::Bool) { result = variant.toBool() ? "true" : "false"; } else if (variant.type() == QVariant::Invalid) { result = "null"; } else if (variant.type() == QVariant::ULongLong) { result = QByteArray::number(variant.toULongLong()); } else if (variant.type() == QVariant::LongLong) { result = QByteArray::number(variant.toLongLong()); } else if (variant.type() == QVariant::Int) { result = QByteArray::number(variant.toInt()); } else if (variant.type() == QVariant::UInt) { result = QByteArray::number(variant.toUInt()); } else if (variant.type() == QVariant::Char) { QChar c = variant.toChar(); if (c.unicode() > 127) result = "\\u" + QByteArray::number(c.unicode(), 16).rightJustified(4, '0'); else result.append(c.toAscii()); } else if (variant.canConvert ()) { result = QByteArray::number(variant.toLongLong()); } else if (variant.canConvert ()) { result = stringify(variant); } return result; } QByteArray prettyStringify(const QVariant &variant, int indent, int indent0) { QByteArray result; QString indentstr0 = QString(indent0, ' '); QString indentstr = QString(indent0 + indent, ' '); switch ((int) variant.type()) { case QVariant::List: case QVariant::StringList: { result += indentstr0; result += "[\n"; QVariantList list = variant.toList(); for (int i = 0; i < list.count(); i++) { if (i != 0) result += ",\n"; if (list[i].type() != QVariant::Map && list[i].type() != QVariant::List && list[i].type() != QVariant::StringList) result += indentstr; result += prettyStringify(list[i], indent, indent0 + indent); } result += "\n"; result += indentstr0; result += "]"; break; } case QVariant::Map: { QVariantMap map = variant.toMap(); QVariantMap::const_iterator it = map.constBegin(); result += indentstr0; result += "{\n"; while (it != map.constEnd()) { if (it != map.constBegin()) result += ",\n"; result += indentstr; result += "\"" + escape(it.key()) + "\":"; if (it.value().type() == QVariant::Map || it.value().type() == QVariant::List || it.value().type() == QVariant::StringList) { result += "\n"; } result += prettyStringify(it.value(), indent, indent0 + indent); ++it; } result += "\n"; result += indentstr0; result += "}"; break; } case QVariant::String: case QVariant::ByteArray: { result = "\"" + escape(variant) + "\""; break; } case QVariant::Double: case QMetaType::Float: { result = QString::number(variant.toDouble(), 'g', 15).toUtf8(); break; } case QVariant::Bool: { result = variant.toBool() ? "true" : "false"; break; } case QVariant::Invalid: { result = "null"; break; } case QVariant::ULongLong: { result = QByteArray::number(variant.toULongLong()); break; } case QVariant::LongLong: { result = QByteArray::number(variant.toLongLong()); break; } case QVariant::Int: { result = QByteArray::number(variant.toInt()); break; } case QVariant::UInt: { result = QByteArray::number(variant.toUInt()); break; } case QVariant::Char: { QChar c = variant.toChar(); if (c.unicode() > 127) result = "\\u" + QByteArray::number(c.unicode(), 16).rightJustified(4, '0'); else result.append(c.toAscii()); break; } default: { if (variant.canConvert ()) { result = QByteArray::number(variant.toLongLong()); } else if (variant.canConvert ()) { result = stringify(variant); } break; } } return result; } }