有没有办法在 qml 中键入从 json 解析的对象

Posted

技术标签:

【中文标题】有没有办法在 qml 中键入从 json 解析的对象【英文标题】:Is there a way to type an object parsed from json in qml 【发布时间】:2021-08-16 16:48:22 【问题描述】:

json文件是这样的。我想在 qml 中为它定义一个类,就像 typescript 中的 interface 关键字一样。


    "ScannerID": "ID",
    "Status": 1,
    "SuccessRate": 0.999,
    "Result": [
            "Codes": "result_11111",
            "Positions": 
                "CenterX": 10.0,
                "CenterY": 10.0,
                "Width": 100.0,
                "Height": 100.0,
                "Angle": 50
            ,
            "Types": "QrCode"
        ,
        //more items
    ]

我试图在文件ScannerResult.qml中定义一个qml类

import QtQuick 2.4

QtObject 
    property string pScannerID
    property int pStatus
    property real pSuccessRate
    // how to define Result with strong type?
    property ? pResult

    function load(obj) 
        pScannerID = obj.ScannerID
        //......
    

那就用吧

...
ScannerResult 
    id: scannerResult


function log(jsonstr) 
    let obj = JSON.parse(jsonstr);
    scannerResult.load(obj)
    console.log(scannerResult.pScannerID) // it works

...

但是"Result"键下的对象向量很难处理。因为 qml 不允许在 A 类下定义 B 类。 那么有没有人知道如何定义一个强类型类来保存从 json 中解析的对象在 qml 中?然后我可以在 qtcreator 中使用具有自动完成功能的类。

【问题讨论】:

“但是'Result'键下的对象向量很难处理。”有什么难的?你的问题到底是什么? @JarMan 这很难,因为 qml 不允许在 A 类下定义 B 类,而我通常在 C++ 中这样做。我的问题是如何定义一个强类型类来保存 qml 中从 json 解析的对象。 "qml 不允许在 A 类下定义 B 类"——我不确定这意味着什么。 inline components 会帮助你吗?或者您可以在 A 类之外定义 B 类吗? @JarMan 内联组件似乎无法容纳长度未知的向量。外部定义会使项目过于复杂。不过谢谢你的回复。 【参考方案1】:

您可以创建一个property var 并将其分配为一个列表/数组/向量来保存pResult。要填充此列表,您可以创建“B 类”Component,并在解析 JSON 对象时动态创建此类的实例。

使用您的代码结构,这里是ScannerResult.qml 的更新版本:

import QtQuick 2.4

QtObject 
    property string pScannerID
    property int pStatus
    property real pSuccessRate
    property var pResult: []

    function load(obj) 
        pScannerID = obj.ScannerID
        //... etc
        for (var element of obj.Result) 
            let resultQtObject = resultComponent.createObject(this, )
            resultQtObject.pCodes = element.Codes
            resultQtObject.pTypes = element.Types
            resultQtObject.pPositions.pCenterX = element.Positions.CenterX
            //... etc
            pResult.push(resultQtObject)
        
    

    property Component resultComponent: Component 

        QtObject 
            property string pCodes
            property string pTypes
            property QtObject pPositions: QtObject 
                property real pCenterX
                property real pCenterY
                property real pWidth
                property real pHeight
                property int pAngle
            
        
    

您更新后的log 函数的工作原理如下:

    function log(jsonstr) 
        let obj = JSON.parse(jsonstr);
        scannerResult.load(obj)
        console.log(scannerResult.pScannerID) // it works
        console.log(scannerResult.pResult[0].pPositions.pCenterX) // it works
    

因为您是在运行时动态创建此Component 的实例,QtCreator 无法为其提供自动完成建议。正如您提到的,您的向量长度未知,我相信运行时实例化是您唯一的选择,因此没有可以适应自动完成的解决方案。

另外需要注意的是,如果您多次重新运行log()/load(),您将需要清理pResult 列表和destroy() 动态创建的对象。

【讨论】:

以上是关于有没有办法在 qml 中键入从 json 解析的对象的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 qml 中从网上下载图像

QML 语言基础

如何在Qt C++中解析JSON数据并使之被QML应用 / 蓝讯

如何从 C++ 访问特定 QML 控件的事件

有没有办法在占位符文本 QML 中为特定单词着色?

JSON.parse解析出错解决办法