Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort a QJsonArray by one of its child elements

Tags:

c++

json

sorting

qt

How do I implement custom sorting of a QJsonArray based on one of its children?

I have QJsonArray toys based on this JSON:

"toys": [
    {
        "type": "teddy",
        "name": "Thomas",
        "size": 24
    },
    {
        "type": "giraffe",
        "name": "Jenny",
        "size": 28
    },
    {
        "type": "alligator",
        "name": "Alex",
        "size": 12
    }
]

I want to sort this alphabetically by "name".

I tried this:

std::sort(toys.begin(), toys.end(), [](const QJsonObject &v1, const QJsonObject &v2) {
    return v1["name"].toString() < v2["name"].toString();
});

but this throws lots of errors.

like image 315
Paul Masri-Stone Avatar asked Jan 01 '23 08:01

Paul Masri-Stone


1 Answers

There are a couple of things that need fixing. First, here's my solution and below some explanations:

Solution

inline void swap(QJsonValueRef v1, QJsonValueRef v2)
{
    QJsonValue temp(v1);
    v1 = QJsonValue(v2);
    v2 = temp;
}

std::sort(toys.begin(), toys.end(), [](const QJsonValue &v1, const QJsonValue &v2) {
    return v1.toObject()["name"].toString() < v2.toObject()["name"].toString();
});

Explanation

Comparison arguments

One of the errors you had was:

no matching function for call to object of type '(lambda at xxxxxxxx)'
        if (__comp(*--__last, *__first))
            ^~~~~~

...

candidate function not viable: no known conversion from 'QJsonValueRef' to 'const QJsonObject' for 1st argument
std::sort(toys.begin(), toys.end(), [](const QJsonObject &v1, const QJsonObject &v2) {
                                    ^
...

The iterator does not know that your array elements are of type QJsonObject. Instead it sees them as the generic QJsonValue type. There's no automatic conversion to QJsonObject, so it throws an error with your lambda function.

Replace const QJsonObject & with const QJsonValue & for both lambda arguments. Then handle the conversion to QJsonObject type explicitly in the function body: v1.toObject()... instead of v1....

No swap function!

One of the errors you had was:

no matching function for call to 'swap'
            swap(*__first, *__last);
            ^~~~

As discussed in Qt bug report QTBUG-44944, Qt does not provide an implementation for swapping over the two QJsonValue elements in the array. Thanks to the bug reporter Keith Gardner, we can include our own swap function. As suggested in the report, you may want to put that as an inline function in a global header file.

like image 74
Paul Masri-Stone Avatar answered Jan 13 '23 20:01

Paul Masri-Stone