mirror of
https://bitbucket.org/smil3y/katie.git
synced 2025-02-23 18:32:55 +00:00
partial rootless JSON arrays support
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
5b0fcfa529
commit
808d94b266
4 changed files with 178 additions and 89 deletions
|
@ -32,21 +32,21 @@ class QJsonDocumentPrivate {
|
|||
public:
|
||||
QJsonDocumentPrivate() : ref(1) { }
|
||||
|
||||
QVariantMap jsonToMap(const QByteArray &jsondata);
|
||||
void mapToJson(const QVariantMap &jsonmap, json_t *jroot, quint16 jdepth);
|
||||
QVariant jsonToVariant(const QByteArray &jsondata);
|
||||
void variantToJson(const QVariant &jsonvariant, json_t *jroot, quint16 jdepth);
|
||||
|
||||
QAtomicInt ref;
|
||||
QByteArray json;
|
||||
QVariantMap map;
|
||||
QVariant variant;
|
||||
QString error;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QJsonDocumentPrivate);
|
||||
};
|
||||
|
||||
QVariantMap QJsonDocumentPrivate::jsonToMap(const QByteArray &jsondata)
|
||||
QVariant QJsonDocumentPrivate::jsonToVariant(const QByteArray &jsondata)
|
||||
{
|
||||
QVariantMap result;
|
||||
QVariant result;
|
||||
|
||||
if (jsondata.isEmpty()) {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Data is empty");
|
||||
|
@ -63,13 +63,14 @@ QVariantMap QJsonDocumentPrivate::jsonToMap(const QByteArray &jsondata)
|
|||
|
||||
switch(json_typeof(jroot)) {
|
||||
case JSON_OBJECT: {
|
||||
QVariantMap mapresult;
|
||||
const char *jkey;
|
||||
json_t *jobject;
|
||||
json_object_foreach(jroot, jkey, jobject) {
|
||||
switch(json_typeof(jobject)) {
|
||||
case JSON_OBJECT: {
|
||||
char* jdata = json_dumps(jobject, 0);
|
||||
result.insert(jkey, jsonToMap(jdata));
|
||||
mapresult.insert(jkey, jsonToVariant(jdata));
|
||||
::free(jdata);
|
||||
break;
|
||||
}
|
||||
|
@ -80,7 +81,7 @@ QVariantMap QJsonDocumentPrivate::jsonToMap(const QByteArray &jsondata)
|
|||
switch(json_typeof(jarray)) {
|
||||
case JSON_OBJECT: {
|
||||
char* jdata = json_dumps(jarray, 0);
|
||||
listvalue.append(jsonToMap(jdata));
|
||||
listvalue.append(jsonToVariant(jdata));
|
||||
::free(jdata);
|
||||
break;
|
||||
}
|
||||
|
@ -114,31 +115,31 @@ QVariantMap QJsonDocumentPrivate::jsonToMap(const QByteArray &jsondata)
|
|||
}
|
||||
}
|
||||
}
|
||||
result.insert(jkey, listvalue);
|
||||
mapresult.insert(jkey, listvalue);
|
||||
break;
|
||||
}
|
||||
case JSON_STRING: {
|
||||
result.insert(jkey, QVariant(json_string_value(jobject)));
|
||||
mapresult.insert(jkey, QVariant(json_string_value(jobject)));
|
||||
break;
|
||||
}
|
||||
case JSON_INTEGER: {
|
||||
result.insert(jkey, QVariant(json_integer_value(jobject)));
|
||||
mapresult.insert(jkey, QVariant(json_integer_value(jobject)));
|
||||
break;
|
||||
}
|
||||
case JSON_REAL: {
|
||||
result.insert(jkey, QVariant(json_real_value(jobject)));
|
||||
mapresult.insert(jkey, QVariant(json_real_value(jobject)));
|
||||
break;
|
||||
}
|
||||
case JSON_TRUE: {
|
||||
result.insert(jkey, QVariant(true));
|
||||
mapresult.insert(jkey, QVariant(true));
|
||||
break;
|
||||
}
|
||||
case JSON_FALSE: {
|
||||
result.insert(jkey, QVariant(false));
|
||||
mapresult.insert(jkey, QVariant(false));
|
||||
break;
|
||||
}
|
||||
case JSON_NULL: {
|
||||
result.insert(jkey, QVariant());
|
||||
mapresult.insert(jkey, QVariant());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -147,10 +148,55 @@ QVariantMap QJsonDocumentPrivate::jsonToMap(const QByteArray &jsondata)
|
|||
}
|
||||
}
|
||||
}
|
||||
result = mapresult;
|
||||
break;
|
||||
}
|
||||
case JSON_ARRAY: {
|
||||
QVariantList listvalue;
|
||||
for (size_t i = 0; i < json_array_size(jroot); i++) {
|
||||
json_t *jarray = json_array_get(jroot, i);
|
||||
switch(json_typeof(jarray)) {
|
||||
case JSON_OBJECT: {
|
||||
char* jdata = json_dumps(jarray, 0);
|
||||
listvalue.append(jsonToVariant(jdata));
|
||||
::free(jdata);
|
||||
break;
|
||||
}
|
||||
case JSON_STRING: {
|
||||
listvalue.append(QVariant(json_string_value(jarray)));
|
||||
break;
|
||||
}
|
||||
case JSON_INTEGER: {
|
||||
listvalue.append(QVariant(json_integer_value(jarray)));
|
||||
break;
|
||||
}
|
||||
case JSON_REAL: {
|
||||
listvalue.append(QVariant(json_real_value(jarray)));
|
||||
break;
|
||||
}
|
||||
case JSON_TRUE: {
|
||||
listvalue.append(QVariant(true));
|
||||
break;
|
||||
}
|
||||
case JSON_FALSE: {
|
||||
listvalue.append(QVariant(false));
|
||||
break;
|
||||
}
|
||||
case JSON_NULL: {
|
||||
listvalue.append(QVariant());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Unknown JSON type in array");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
result = listvalue;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Rootless array/values are not supported");
|
||||
error = QCoreApplication::translate("QJsonDocument", "Rootless values are not supported");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -162,72 +208,105 @@ QVariantMap QJsonDocumentPrivate::jsonToMap(const QByteArray &jsondata)
|
|||
return result;
|
||||
}
|
||||
|
||||
void QJsonDocumentPrivate::mapToJson(const QVariantMap &jsonmap, json_t *jroot, quint16 jdepth)
|
||||
void QJsonDocumentPrivate::variantToJson(const QVariant &jsonvariant, json_t *jroot, quint16 jdepth)
|
||||
{
|
||||
if (jsonmap.isEmpty()) {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Data map is empty");
|
||||
if (jsonvariant.isNull()) {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Data variant is null");
|
||||
return;
|
||||
} else if (Q_UNLIKELY(jdepth >= JSON_PARSER_MAX_DEPTH)) {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Maximum depth reached");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach(const QString &key, jsonmap.keys()) {
|
||||
const QVariant value = jsonmap.value(key);
|
||||
const QByteArray bytearraykey = key.toUtf8();
|
||||
switch(value.type()) {
|
||||
case QVariant::Invalid: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_null());
|
||||
break;
|
||||
switch (jsonvariant.type()) {
|
||||
case QVariant::Map:
|
||||
case QVariant::Hash: {
|
||||
const QVariantMap jsonmap = jsonvariant.toMap();
|
||||
if (jdepth == 1 && jsonmap.isEmpty()) {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Data variant is null");
|
||||
return;
|
||||
}
|
||||
case QVariant::Bool: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), value.toBool() ? json_true() : json_false());
|
||||
break;
|
||||
}
|
||||
case QVariant::Int:
|
||||
case QVariant::LongLong: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_integer(value.toLongLong()));
|
||||
break;
|
||||
}
|
||||
case QVariant::UInt:
|
||||
case QVariant::ULongLong: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_integer(value.toULongLong()));
|
||||
break;
|
||||
}
|
||||
case QVariant::Float:
|
||||
case QVariant::Double: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_real(value.toReal()));
|
||||
break;
|
||||
}
|
||||
case QVariant::ByteArray:
|
||||
case QVariant::String: {
|
||||
const QByteArray bytearrayvalue = value.toByteArray();
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_string(bytearrayvalue.constData()));
|
||||
break;
|
||||
}
|
||||
case QVariant::List: // this works only for QString-convertable types
|
||||
case QVariant::StringList: {
|
||||
json_t *jarray = json_array();
|
||||
foreach(const QString &listvalue, value.toStringList()) {
|
||||
const QByteArray bytearrayvalue = listvalue.toUtf8();
|
||||
json_array_append_new(jarray, json_stringn_nocheck(bytearrayvalue.constData(), bytearrayvalue.size()));
|
||||
foreach(const QString &key, jsonmap.keys()) {
|
||||
const QVariant value = jsonmap.value(key);
|
||||
const QByteArray bytearraykey = key.toUtf8();
|
||||
switch(value.type()) {
|
||||
case QVariant::Invalid: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_null());
|
||||
break;
|
||||
}
|
||||
case QVariant::Bool: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), value.toBool() ? json_true() : json_false());
|
||||
break;
|
||||
}
|
||||
case QVariant::Int:
|
||||
case QVariant::LongLong: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_integer(value.toLongLong()));
|
||||
break;
|
||||
}
|
||||
case QVariant::UInt:
|
||||
case QVariant::ULongLong: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_integer(value.toULongLong()));
|
||||
break;
|
||||
}
|
||||
case QVariant::Float:
|
||||
case QVariant::Double: {
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_real(value.toReal()));
|
||||
break;
|
||||
}
|
||||
case QVariant::ByteArray:
|
||||
case QVariant::String: {
|
||||
const QByteArray bytearrayvalue = value.toByteArray();
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), json_string(bytearrayvalue.constData()));
|
||||
break;
|
||||
}
|
||||
case QVariant::List: // this works only for QString-convertable types
|
||||
case QVariant::StringList: {
|
||||
json_t *jarray = json_array();
|
||||
foreach(const QString &listvalue, value.toStringList()) {
|
||||
const QByteArray bytearrayvalue = listvalue.toUtf8();
|
||||
json_array_append_new(jarray, json_stringn_nocheck(bytearrayvalue.constData(), bytearrayvalue.size()));
|
||||
}
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), jarray);
|
||||
break;
|
||||
}
|
||||
case QVariant::Hash:
|
||||
case QVariant::Map: {
|
||||
jdepth++;
|
||||
json_t *jrootn = json_object();
|
||||
variantToJson(value.toMap(), jrootn, jdepth);
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), jrootn);
|
||||
jdepth--;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Unknown variant type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), jarray);
|
||||
break;
|
||||
}
|
||||
case QVariant::Hash:
|
||||
case QVariant::Map: {
|
||||
jdepth++;
|
||||
json_t *jrootn = json_object();
|
||||
mapToJson(value.toMap(), jrootn, jdepth);
|
||||
json_object_set_new_nocheck(jroot, bytearraykey.constData(), jrootn);
|
||||
jdepth--;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Unknown JSON type");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QVariant::Invalid:
|
||||
case QVariant::Bool:
|
||||
case QVariant::Int:
|
||||
case QVariant::LongLong:
|
||||
case QVariant::UInt:
|
||||
case QVariant::ULongLong:
|
||||
case QVariant::Float:
|
||||
case QVariant::Double:
|
||||
case QVariant::ByteArray:
|
||||
case QVariant::String: {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Rootless values are not supported");
|
||||
break;
|
||||
}
|
||||
case QVariant::List:
|
||||
case QVariant::StringList: {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Rootless arrays are not supported");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
error = QCoreApplication::translate("QJsonDocument", "Unknown variant type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,9 +362,9 @@ QJsonDocument QJsonDocument::fromVariant(const QVariant &variant)
|
|||
static const size_t jflags = JSON_SORT_KEYS | JSON_INDENT(4);
|
||||
|
||||
QScopedPointer<QJsonDocumentPrivate> d(new QJsonDocumentPrivate());
|
||||
d->map = variant.toMap();
|
||||
d->variant = variant;
|
||||
json_t *jroot = json_object();
|
||||
d->mapToJson(d->map, jroot, 1);
|
||||
d->variantToJson(d->variant, jroot, 1);
|
||||
char *jdata = json_dumps(jroot, jflags);
|
||||
d->json = jdata;
|
||||
::free(jdata);
|
||||
|
@ -294,7 +373,7 @@ QJsonDocument QJsonDocument::fromVariant(const QVariant &variant)
|
|||
QJsonDocument jd;
|
||||
if (Q_UNLIKELY(!d->error.isEmpty())) {
|
||||
d->json.clear();
|
||||
d->map.clear();
|
||||
d->variant.clear();
|
||||
}
|
||||
|
||||
jd.d_ptr = d.take();
|
||||
|
@ -319,7 +398,7 @@ QVariant QJsonDocument::toVariant() const
|
|||
return QVariant();
|
||||
}
|
||||
|
||||
return d->map;
|
||||
return d->variant;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -334,11 +413,11 @@ QJsonDocument QJsonDocument::fromJson(const QByteArray &json)
|
|||
{
|
||||
QScopedPointer<QJsonDocumentPrivate> d(new QJsonDocumentPrivate());
|
||||
d->json = json;
|
||||
d->map = d->jsonToMap(json);
|
||||
d->variant = d->jsonToVariant(json);
|
||||
|
||||
if (Q_UNLIKELY(!d->error.isEmpty())) {
|
||||
d->json.clear();
|
||||
d->map.clear();
|
||||
d->variant.clear();
|
||||
}
|
||||
|
||||
QJsonDocument jd;
|
||||
|
@ -373,7 +452,7 @@ bool QJsonDocument::operator==(const QJsonDocument &other) const
|
|||
return false;
|
||||
}
|
||||
|
||||
return (d->json == other.d_ptr->json && d->map == other.d_ptr->map);
|
||||
return (d->json == other.d_ptr->json && d->variant == other.d_ptr->variant);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -393,7 +472,7 @@ bool QJsonDocument::operator==(const QJsonDocument &other) const
|
|||
bool QJsonDocument::isNull() const
|
||||
{
|
||||
Q_D(const QJsonDocument);
|
||||
return (!d || (d->json.isEmpty() && d->map.isEmpty()));
|
||||
return (!d || (d->json.isEmpty() && d->variant.isNull()));
|
||||
}
|
||||
|
||||
QString QJsonDocument::errorString() const
|
||||
|
|
|
@ -145,7 +145,7 @@ void tst_QJsonDocument::error()
|
|||
QVERIFY(jsondoc.isNull());
|
||||
|
||||
jsondoc = QJsonDocument::fromVariant(QVariantMap());
|
||||
QCOMPARE(jsondoc.errorString(), QLatin1String("Data map is empty"));
|
||||
QCOMPARE(jsondoc.errorString(), QLatin1String("Data variant is null"));
|
||||
QVERIFY(jsondoc.isNull());
|
||||
|
||||
// TODO: indermediate error test, e.g. maximum depth reached
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-02-19 20:09+0200\n"
|
||||
"POT-Creation-Date: 2022-02-21 08:48+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -321,31 +321,41 @@ msgctxt "QJsonDocument"
|
|||
msgid "Data is empty"
|
||||
msgstr ""
|
||||
|
||||
#: src/core/tools/qjsondocument.cpp:112
|
||||
#: src/core/tools/qjsondocument.cpp:113 src/core/tools/qjsondocument.cpp:190
|
||||
msgctxt "QJsonDocument"
|
||||
msgid "Unknown JSON type in array"
|
||||
msgstr ""
|
||||
|
||||
#: src/core/tools/qjsondocument.cpp:145 src/core/tools/qjsondocument.cpp:228
|
||||
#: src/core/tools/qjsondocument.cpp:146
|
||||
msgctxt "QJsonDocument"
|
||||
msgid "Unknown JSON type"
|
||||
msgstr ""
|
||||
|
||||
#: src/core/tools/qjsondocument.cpp:153
|
||||
#: src/core/tools/qjsondocument.cpp:199 src/core/tools/qjsondocument.cpp:299
|
||||
msgctxt "QJsonDocument"
|
||||
msgid "Rootless array/values are not supported"
|
||||
msgid "Rootless values are not supported"
|
||||
msgstr ""
|
||||
|
||||
#: src/core/tools/qjsondocument.cpp:168
|
||||
#: src/core/tools/qjsondocument.cpp:214 src/core/tools/qjsondocument.cpp:226
|
||||
msgctxt "QJsonDocument"
|
||||
msgid "Data map is empty"
|
||||
msgid "Data variant is null"
|
||||
msgstr ""
|
||||
|
||||
#: src/core/tools/qjsondocument.cpp:171
|
||||
#: src/core/tools/qjsondocument.cpp:217
|
||||
msgctxt "QJsonDocument"
|
||||
msgid "Maximum depth reached"
|
||||
msgstr ""
|
||||
|
||||
#: src/core/tools/qjsondocument.cpp:282 src/core/tools/qjsondocument.cpp:308
|
||||
msgctxt "QJsonDocument"
|
||||
msgid "Unknown variant type"
|
||||
msgstr ""
|
||||
|
||||
#: src/core/tools/qjsondocument.cpp:304
|
||||
msgctxt "QJsonDocument"
|
||||
msgid "Rootless arrays are not supported"
|
||||
msgstr ""
|
||||
|
||||
#: src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp:82
|
||||
msgctxt "QDeclarativeAnimatedImage"
|
||||
msgid "Katie was built without support for QMovie"
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-02-19 20:09+0200\n"
|
||||
"POT-Creation-Date: 2022-02-21 08:48+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
Loading…
Add table
Reference in a new issue