【问题标题】:How to parse Json array object?如何解析 Json 数组对象?
【发布时间】:2019-01-14 15:08:18
【问题描述】:

我正在尝试在 Qt 应用程序中解析 Json 文件,但我卡在了一个点上。 我有一个 json 文件,其中包含具有属性的数组。现在我有一个 Category 类,它有一个 items 作为成员变量。现在我想解析属性并创建一个唯一的类别对象,在这个对象下我想添加属性。

我通过硬编码实现了这一点:

auto vehicle = std::make_unique<Item>("Coordinates");
vehicle->addEntry(std::make_unique<PropertyItem>("TODO", "x", PropertyType::FLOAT, false, *vehicle.get()));
categories.emplace_back(std::move(vehicle));

void Model::loadItemsFromJson() {
    // Vehicle
    QJsonObject obj = loadJsonFile(":/jsonfiles/vehicle.json");
    QJsonArray properties = obj["properties"].toArray();
   /// No idea here how to achive
}

我应该更改 Json 以便更好地处理还是可以轻松实现? 谢谢

--------------编辑-------- -

Now my json looks like this:
{
    "General": [{
            "Address": "TODO",
            "Readonly": false
        },
    ],
    "Coordinates": [{
            "Address": "TODO",
            "Readonly": false
        }
    ]
    ]
}

和我的实现:

QJsonObject obj = loadJsonFile(":/jsonfiles/vehicle.json");
QVariantMap map = obj.toVariantMap();
for (auto& m : map.keys()) {
// How to create objects??
}

【问题讨论】:

  • 硬编码数据似乎与 JSON 数据不匹配。 “test2”“x”是否对应“世界坐标”“X”?
  • 已更改。 test2 实际上是地址,WorldCoordinates 是类别。像这样:ScenarioPropertyItem(const QString &address, const QString &displayName, PropertyType type, bool readOnly, CategoryItem &parentItem);
  • 如果您要定义 JSON 的结构,我建议它与对象的结构相匹配。 {"Categories":{ "General" : [{"Address" : "TODO", "Name" : "Name", "Type" : "string", "ReadOnly" : "true"}, ...], "World Coordinates" : [...] }
  • 是的,我可以,您能否就创建硬编码中提到的对象提供建议。
  • QVariantMap map = obj.toVariantMap(); for (auto& m : map.keys()) { std::make_unique(m); qDebug()

标签: json qt c++11 c++14


【解决方案1】:

如果您像对象一样构建 JSON,例如

{ 
"Categories" : {        
    "General" : [{
        "Address" : "TODO", 
        "Name" : "Name", 
        "Type" : "string", 
        "ReadOnly" : "true"
        }, ...], 
    "World Coordinates" : [...] 
}

然后你只需解析出每个CategoryItem 和ScenarioPropertyItem

PropertyType toPropertyType(QJsonValue value); // forward declare

void ScenarioPropertiesModel::loadItemsFromJson() {
    // Vehicle
    QJsonObject obj = loadJsonFile(":/jsonfiles/vehicle.json")["Categories"].toObject();
    for (auto & cat : obj)
    {
        auto category = std::make_unique<CategoryItem>(cat.name());
        for (auto & prop : cat.value().toArray())
        {
            auto address = prop["Address"].toString();
            auto name = prop["Name"].toString();
            auto type = toPropertyType(prop["Type"]);
            auto readonly = prop["Readonly"].toBool();
            category->addEntry(std::make_unique<ScenarioPropertyItem>(address, name, type, readonly));
        }
        categories.emplace_back(std::move(category));
    }
}

PropertyType toPropertyType(QJsonValue value)
{
    static std::map<QString, PropertyType> propertyTypes = 
    { 
        { "float", PropertyType::FLOAT },
        { "string", PropertyType::String },
        // etc
    }
    return propertyTypes[value.toString()];
}

【讨论】:

  • 非常感谢。它帮了大忙。但有一点是 obj[cat] 产生错误,说它不返回迭代器。
  • 你是最棒的,谢谢。应该是这样的: for (auto& prop : obj[cat].toArray()) { auto address = prop.toObject().value("Address").toString();
  • 您不需要toObject().value(...)。 QJsonValue::operator[] 被定义为等价
  • 我想再问一个问题。将 QJsonobject 传递给每个副本的函数很重吗?因为我有这样的东西: QJsonObject obj;签名:QJsonObject loadJsonFile(const QString& filePath); void parseJsonObject(QJsonObject 对象); obj = loadJsonFile(":/jsonfiles/vehicle.json"); parseJsonObject(obj); // 行人 obj = loadJsonFile(":/jsonfiles/pedestrian.json"); parseJsonObject(obj); // MiscObject obj = loadJsonFile(":/jsonfiles/miscobject.json"); parseJsonObject(obj);还是我应该使用指针
  • @vinaycool 所有QJson... 类都是隐式共享的(“Copy-on-Write”),这意味着它们是轻量级的传递。如果您将参数限定为const,那么您可以确信它们不会被复制
猜你喜欢
  • 2019-12-01
  • 1970-01-01
  • 2021-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多