C++ QJson数据序列化顺序

C++ QJson数据序列化顺序,c++,json,qt,C++,Json,Qt,我已经实现了一个代码,它将从QLineEdit获取输入,数据将以json文件格式保存 void MainWindow::fileWriteOperationJson() { QString filename = "C:/Users/.../Documents/Qt/save.json"; QFile saveFile(filename); saveFile.open(QIODevice::WriteOnly|QIODevice::Text); if (!

我已经实现了一个代码,它将从
QLineEdit
获取输入,数据将以json文件格式保存

void MainWindow::fileWriteOperationJson()
{    
    QString filename = "C:/Users/.../Documents/Qt/save.json";
    QFile saveFile(filename);
    saveFile.open(QIODevice::WriteOnly|QIODevice::Text);

    if (!saveFile.open(QIODevice::WriteOnly))
    {
          qWarning("Couldn't open save file.");    
    }

    QJsonObject obj; //this is the root
    QJsonArray personalData;    

    QJsonObject json;
    json["name"] = ui->nameLineEdit->text();
    json["address"] = ui->addressLineEdit->toPlainText();

    personalData.append(json);
    obj["personalData"] = personalData;

    QTextStream out(&saveFile);

    out << QJsonDocument(obj).toJson(QJsonDocument::Indented);    

}
但是,我有这样的结果

"address" = xyz
"name" = xyz
如何获得预期订单?

因此,结构很重要,但项目的顺序并不重要

如果需要按特定顺序打印项目,则需要将它们从Json提取到合适的数据结构中,并自行处理


或者,您可以保存为不同的格式,但请注意,Qt的XML与Json的作用相同。也许a对您更有用。

Qt使用按字母顺序排序的键生成JSON数据。好吧,没办法绕过它。不过,您可以尝试使用单个键/值对将对象封装到数组中,并保留顺序:

[
     {"address": xyz},
     {"name": xyz}
]

或者您可以尝试使用不同的存储格式。

根本的问题是QMap没有一个有序的表单。 下面是一个可能的解决方案,将QVariantMap子类化:

#ifndef ORDEREDVARIANTMAP_H
#define ORDEREDVARIANTMAP_H

#include <QtCore>

class OrderedVariantMap : public QMap<QString, QVariant> {
// Test:
//    OrderedVariantMap test_map;
//    test_map.insert("xxx", 1);
//    test_map.insert("aaa", 2);
//    test_map.insert("kkk", 3);

//    test_map["321"] = 4;
//    test_map["000"] = 5;
//    test_map["123"] = 6;

//    qDebug() << "QMap.keys()" << test_map.keys();
//    qDebug() << "QMap.orderedKeys()" << test_map.orderedKeys();

//    QVariant test_variant;
//    test_variant.setValue(test_map);
//    qDebug() << "test_variant.typeName()" << test_variant.typeName();
//    OrderedVariantMap test_map_recovered = qvariant_cast<OrderedVariantMap>(test_variant);
//    qDebug() << "test_map_recovered.orderedKeys()" << test_map_recovered.orderedKeys();

// Test results:
//    QMap.keys() ("000", "123", "321", "aaa", "kkk", "xxx")
//    QMap.orderedKeys() ("xxx", "aaa", "kkk", "321", "000", "123")
//    test_variant.typeName() OrderedVariantMap
//    test_map_recovered.orderedKeys() ("xxx", "aaa", "kkk", "321", "000", "123")

public:
    OrderedVariantMap ( );
    ~OrderedVariantMap ( );

void
clear ( );

void // QMap::iterator
insert ( const QString &key,
         const QVariant &value );

QVariant&
operator[] ( const QString &key );

const QVariant
operator[] ( const QString &key ) const;

const QString
orderedKey ( int index ) const;

const QVariant
orderedValue ( int index ) const;

QStringList
orderedKeys ( ) const ;

private:
    QStringList Ordered_Keys;

protected:

};

Q_DECLARE_METATYPE(OrderedVariantMap)

#endif // ORDEREDVARIANTMAP_H

可以提供更多功能,例如有序迭代器。

使用不同的格式。项目的顺序在Json中并不重要;重要的只是结构。Qt选择按字母顺序排列,我不相信有任何API可以改变这一点。Qt的XML实现也是如此,我真的很想这样做。我尝试了它,并结合
QJsonObject::fromVariantMap
,它看起来几乎很有希望。甚至fromVariant映射实现也假定
QVariantMap
已排序,并在其上使用标准迭代器。问题是像
begin
end
这样的函数不是虚拟的,因此
qjsonobject
不会使用您的实现。几乎正确。对于JSON数组实体,保留项的顺序。它是唯一不保留顺序的JSON对象实体。
#ifndef ORDEREDVARIANTMAP_H
#define ORDEREDVARIANTMAP_H

#include <QtCore>

class OrderedVariantMap : public QMap<QString, QVariant> {
// Test:
//    OrderedVariantMap test_map;
//    test_map.insert("xxx", 1);
//    test_map.insert("aaa", 2);
//    test_map.insert("kkk", 3);

//    test_map["321"] = 4;
//    test_map["000"] = 5;
//    test_map["123"] = 6;

//    qDebug() << "QMap.keys()" << test_map.keys();
//    qDebug() << "QMap.orderedKeys()" << test_map.orderedKeys();

//    QVariant test_variant;
//    test_variant.setValue(test_map);
//    qDebug() << "test_variant.typeName()" << test_variant.typeName();
//    OrderedVariantMap test_map_recovered = qvariant_cast<OrderedVariantMap>(test_variant);
//    qDebug() << "test_map_recovered.orderedKeys()" << test_map_recovered.orderedKeys();

// Test results:
//    QMap.keys() ("000", "123", "321", "aaa", "kkk", "xxx")
//    QMap.orderedKeys() ("xxx", "aaa", "kkk", "321", "000", "123")
//    test_variant.typeName() OrderedVariantMap
//    test_map_recovered.orderedKeys() ("xxx", "aaa", "kkk", "321", "000", "123")

public:
    OrderedVariantMap ( );
    ~OrderedVariantMap ( );

void
clear ( );

void // QMap::iterator
insert ( const QString &key,
         const QVariant &value );

QVariant&
operator[] ( const QString &key );

const QVariant
operator[] ( const QString &key ) const;

const QString
orderedKey ( int index ) const;

const QVariant
orderedValue ( int index ) const;

QStringList
orderedKeys ( ) const ;

private:
    QStringList Ordered_Keys;

protected:

};

Q_DECLARE_METATYPE(OrderedVariantMap)

#endif // ORDEREDVARIANTMAP_H
#include "OrderedVariantMap.h"

OrderedVariantMap::OrderedVariantMap ( ) : QMap ( ) {

}

OrderedVariantMap::~OrderedVariantMap ( ) {

}

QStringList
OrderedVariantMap::orderedKeys ( ) const {
    return Ordered_Keys;
}

void
OrderedVariantMap::clear ( ) {
    Ordered_Keys.clear();
    QMap::clear();
}

void // QMap::iterator
OrderedVariantMap::insert ( const QString &key,
                            const QVariant &value ) {
    Ordered_Keys.append(key);
    QMap::insert(key, value);
}

QVariant&
OrderedVariantMap::operator[] ( const QString &key ) {
    Ordered_Keys.append(key);
    return QMap::operator [](key);
}

const QVariant
OrderedVariantMap::operator[] ( const QString &key ) const {
    return this->value(key);
}

const QString
OrderedVariantMap::orderedKey ( int index ) const {
    return Ordered_Keys[index];
}

const QVariant
OrderedVariantMap::orderedValue ( int index ) const {
    return this->value(Ordered_Keys[index]);
}