|
|
|
|
@ -17,51 +17,138 @@ |
|
|
|
|
* ============================================================ */ |
|
|
|
|
#include "json.h" |
|
|
|
|
|
|
|
|
|
#if QT_VERSION < 0x050000 |
|
|
|
|
#include <qjson/parser.h> |
|
|
|
|
#include <qjson/serializer.h> |
|
|
|
|
#else |
|
|
|
|
#include <QJsonDocument> |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
QVariant Json::parse(const QByteArray &data, bool* ok) |
|
|
|
|
#include <QScriptEngine> |
|
|
|
|
#include <QScriptValueIterator> |
|
|
|
|
|
|
|
|
|
// Class based on http://stackoverflow.com/a/15805783
|
|
|
|
|
|
|
|
|
|
Json::Json() |
|
|
|
|
: m_engine(0) |
|
|
|
|
, m_ok(true) |
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Json::~Json() |
|
|
|
|
{ |
|
|
|
|
delete m_engine; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QVariant Json::parse(const QString &data) |
|
|
|
|
{ |
|
|
|
|
#if QT_VERSION < 0x050000 |
|
|
|
|
QJson::Parser parser; |
|
|
|
|
return parser.parse(data, ok); |
|
|
|
|
#else |
|
|
|
|
QJsonParseError error; |
|
|
|
|
QJsonDocument doc = QJsonDocument::fromJson(data, &error); |
|
|
|
|
|
|
|
|
|
if (ok) { |
|
|
|
|
*ok = error.error == QJsonParseError::NoError; |
|
|
|
|
delete m_engine; |
|
|
|
|
m_engine = new QScriptEngine(); |
|
|
|
|
|
|
|
|
|
QString jsonData = QString("(%1)").arg(data); |
|
|
|
|
QScriptValue obj = m_engine->evaluate(jsonData); |
|
|
|
|
m_ok = !obj.isError() && obj.isObject(); |
|
|
|
|
|
|
|
|
|
return decodeInner(obj); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QString Json::serialize(const QVariant &variant) |
|
|
|
|
{ |
|
|
|
|
delete m_engine; |
|
|
|
|
m_engine = new QScriptEngine(); |
|
|
|
|
|
|
|
|
|
m_engine->evaluate("function toString() { return JSON.stringify(this, null, ' ') }"); |
|
|
|
|
|
|
|
|
|
QScriptValue toString = m_engine->globalObject().property("toString"); |
|
|
|
|
QScriptValue obj = encodeInner(variant.toMap()); |
|
|
|
|
QScriptValue result = toString.call(obj); |
|
|
|
|
|
|
|
|
|
m_ok = !obj.isError() && obj.isObject(); |
|
|
|
|
return result.toString(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Json::ok() const |
|
|
|
|
{ |
|
|
|
|
return m_ok; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QMap<QString, QVariant> Json::decodeInner(QScriptValue object) |
|
|
|
|
{ |
|
|
|
|
QMap<QString, QVariant> map; |
|
|
|
|
QScriptValueIterator it(object); |
|
|
|
|
|
|
|
|
|
while (it.hasNext()) { |
|
|
|
|
it.next(); |
|
|
|
|
|
|
|
|
|
if (it.value().isArray()) { |
|
|
|
|
map.insert(it.name(), QVariant(decodeInnerToList(it.value()))); |
|
|
|
|
} |
|
|
|
|
else if (it.value().isNumber()) { |
|
|
|
|
map.insert(it.name(), QVariant(it.value().toNumber())); |
|
|
|
|
} |
|
|
|
|
else if (it.value().isString()) { |
|
|
|
|
map.insert(it.name(), QVariant(it.value().toString())); |
|
|
|
|
} |
|
|
|
|
else if (it.value().isNull()) { |
|
|
|
|
map.insert(it.name(), QVariant()); |
|
|
|
|
} |
|
|
|
|
else if (it.value().isObject()) { |
|
|
|
|
map.insert(it.name(), QVariant(decodeInner(it.value()))); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return doc.toVariant(); |
|
|
|
|
#endif |
|
|
|
|
return map; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QByteArray Json::serialize(const QVariant &variant, bool* ok) |
|
|
|
|
QList<QVariant> Json::decodeInnerToList(QScriptValue arrayValue) |
|
|
|
|
{ |
|
|
|
|
#if QT_VERSION < 0x050000 |
|
|
|
|
QJson::Serializer serializer; |
|
|
|
|
#ifdef QJSON_HAVE_INDENT |
|
|
|
|
serializer.setIndentMode(QJson::IndentFull); |
|
|
|
|
#endif |
|
|
|
|
const QByteArray data = serializer.serialize(variant); |
|
|
|
|
|
|
|
|
|
if (ok) { |
|
|
|
|
*ok = !data.isNull(); |
|
|
|
|
QList<QVariant> list; |
|
|
|
|
QScriptValueIterator it(arrayValue); |
|
|
|
|
|
|
|
|
|
while (it.hasNext()) { |
|
|
|
|
it.next(); |
|
|
|
|
|
|
|
|
|
if (it.name() == QLatin1String("length")) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (it.value().isArray()) { |
|
|
|
|
list.append(QVariant(decodeInnerToList(it.value()))); |
|
|
|
|
} |
|
|
|
|
else if (it.value().isNumber()) { |
|
|
|
|
list.append(QVariant(it.value().toNumber())); |
|
|
|
|
} |
|
|
|
|
else if (it.value().isString()) { |
|
|
|
|
list.append(QVariant(it.value().toString())); |
|
|
|
|
} |
|
|
|
|
else if (it.value().isNull()) { |
|
|
|
|
list.append(QVariant()); |
|
|
|
|
} |
|
|
|
|
else if (it.value().isObject()) { |
|
|
|
|
list.append(QVariant(decodeInner(it.value()))); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return data; |
|
|
|
|
#else |
|
|
|
|
QJsonDocument doc = QJsonDocument::fromVariant(variant); |
|
|
|
|
return list; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QScriptValue Json::encodeInner(const QMap<QString, QVariant> &map) |
|
|
|
|
{ |
|
|
|
|
QScriptValue obj = m_engine->newObject(); |
|
|
|
|
QMapIterator<QString, QVariant> i(map); |
|
|
|
|
|
|
|
|
|
while (i.hasNext()) { |
|
|
|
|
i.next(); |
|
|
|
|
|
|
|
|
|
if (ok) { |
|
|
|
|
*ok = !doc.isNull(); |
|
|
|
|
if (i.value().type() == QVariant::String) { |
|
|
|
|
obj.setProperty(i.key(), i.value().toString()); |
|
|
|
|
} |
|
|
|
|
else if (i.value().type() == QVariant::Int) { |
|
|
|
|
obj.setProperty(i.key(), i.value().toInt()); |
|
|
|
|
} |
|
|
|
|
else if (i.value().type() == QVariant::Double) { |
|
|
|
|
obj.setProperty(i.key(), i.value().toDouble()); |
|
|
|
|
} |
|
|
|
|
else if (i.value().type() == QVariant::List) { |
|
|
|
|
obj.setProperty(i.key(), qScriptValueFromSequence(m_engine, i.value().toList())); |
|
|
|
|
} |
|
|
|
|
else if (i.value().type() == QVariant::Map) { |
|
|
|
|
obj.setProperty(i.key(), encodeInner(i.value().toMap())); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return doc.toJson(QJsonDocument::Indented); |
|
|
|
|
#endif |
|
|
|
|
return obj; |
|
|
|
|
} |
|
|
|
|
|