ListModel and JSON Parsing in QML
-
Hello everyone,
I'm working on a QML application where I'm trying to parse a JSON string and populate a ListModel with the data and plot some charts. However, I'm encountering a couple of issues related to accessing the model data.
Here’s a snippet of my code:
import QtQuick import QtQuick.Window import QtCharts Window { width: 640 height: 480 visible: true readonly property string json: "[{\"data\": [1,2,3]},{\"data\": [4,5,6]}]" property ListModel myModel: ListModel {} function parseJson(json) { try { var obj = JSON.parse(json); if (obj) { obj.forEach(function(item) { console.log("json data: " + item.data) myModel.append({ data: item.data }); }); } } catch (e) { console.error("QML JSON parse error: ", e); } } Component.onCompleted: parseJson(json); ListView { anchors.fill: parent model: myModel delegate: ChartView { width: 500 height: 300 LineSeries { id: lineSeries Component.onCompleted: plot() function plot() { console.log("model.data: " + model.data) console.log("model.data.length: " + model.data.length) lineSeries.clear() model.data.forEach(function(value, index) { lineSeries.append(index, value); }); } } } } }
Output:
qml: json data: 1,2,3 qml: json data: 4,5,6 qml: model.data: QQmlListModel(0x131e185e780) qml: model.data.length: undefined qrc:/qt/qml/TestQmlListView/Main.qml:50: TypeError: Property 'forEach' of object QQmlListModel(0x131e185e780) is not a function
When I log model.data, it shows QQmlListModel, but I can't access its contents using forEach. The length property is also undefined. How can I correctly iterate through the data stored in ListModel?
Thank you!
-
@Drazz said in ListModel and JSON Parsing in QML:
How can I correctly iterate through the data stored in ListModel?
The API available on
ListModel
is described in the documentation.You need to use the
count
property and theget(index)
method. You can use these to write a straightforwardfor
loop. -
Thanks for your help but I haven't had any success yet. This is the change I've made based on your suggestion:
function plot() { console.log("model.data: " + model.data) console.log("model.data.count: " + model.data.count) lineSeries.clear() for (var i = 0; i < model.data.count; i++) { console.log("Model " + i + " data " + model.data.get(i) + " value: " + valueOf(model.data.get(i))) lineSeries.append(i, model.data.get(i)) } }
And I get this output:
qml: json data: 1,2,3 qml: json data: 4,5,6 qml: model.data: QQmlListModel(0x25f365eb2e0) qml: model.data.count: 3 qml: Model 0 data QObject(0x25f3679f160) value: DeclarativeLineSeries_QML_1(0x25f361b1db0) Ignored NaN, Inf, or -Inf value. qml: Model 1 data QObject(0x25f3679f6b0) value: DeclarativeLineSeries_QML_1(0x25f361b1db0) Ignored NaN, Inf, or -Inf value. qml: Model 2 data QObject(0x25f3679da00) value: DeclarativeLineSeries_QML_1(0x25f361b1db0) Ignored NaN, Inf, or -Inf value. qml: model.data: QQmlListModel(0x25f365ee220) qml: model.data.count: 3 qml: Model 0 data QObject(0x25f3679e060) value: DeclarativeLineSeries_QML_1(0x25f367f4980) Ignored NaN, Inf, or -Inf value. qml: Model 1 data QObject(0x25f3679e390) value: DeclarativeLineSeries_QML_1(0x25f367f4980) Ignored NaN, Inf, or -Inf value. qml: Model 2 data QObject(0x25f3679de40) value: DeclarativeLineSeries_QML_1(0x25f367f4980) Ignored NaN, Inf, or -Inf value.
-
This work arround works:
[...] readonly property string json: "[{\"data\": [1,2,3]},{\"data\": [4,5,6]}]" property ListModel myModel: ListModel {} function parseJson(json) { try { var obj = JSON.parse(json); if (obj) { obj.forEach(function(item) { console.log("json data: " + item.data) var dataObj= [] item.data.forEach(function(element) { dataObj.push({"value" : element}) }) myModel.append({ data: dataObj }); }); } } catch (e) { console.error("QML JSON parse error: ", e); } } [...] function plot() { console.log("model.data: " + model.data) console.log("model.data.count: " + model.data.count) lineSeries.clear() for (var i = 0; i < model.data.count; i++) { console.log("DataIdx " + i + " dataValue " + model.data.get(i).value) lineSeries.append(i, model.data.get(i).value) } }
Is this the best way to do this?
-
https://github.com/benlau/qsyncable does this with its
JsonListModel
.All you have to do is
source: JSON.parse(json)
and it will diff the model with the previous version and emit corresponding signals (rowsInserted/removed, dataChanged, ...) -