Как проверить Json Файл, если ключи действительны, и создать массив объектов в C ++ с RapidJson - PullRequest
0 голосов
/ 26 марта 2020

Я пытаюсь создать массив класса / структуры из файла json с быстрым json. Файл содержит следующее содержимое:

{
  "item" : [
{"name": "chair",
 "attribute": "iron",
 "available": "false"},

{"Name": "bed",
 "attribute": "wood",
 "available": "true",
 "attribute":"soft"},

{"naeM": "lamp",
 "attribute": "iron",
 "available": "false",
 "Number": "4"},

....

{"name": "mirrow",
 "attribute": "iron",
 "available": "false"}
           ],

"category" : [
{"name": "kitchen"}, {"name": "living room"},{"name": "bedroom"} ]
}

Я просмотрел всю информацию, которую смог получить на быстром json .org, и примеры, но на самом деле не понимаю, как проверить конкретный c введите каждый проверяемый объект массива, если ключ существует (чувствителен к регистру) и в нем нет дубликатов.

Например, здесь я хочу проверить, есть ли в каждом объекте массива ключ "name" или если присутствуют только ключи «имя», «атрибут» и «доступно». Вероятно, закрытый доступ к нему должен был бы создать действительную проверку json схемы, но я не совсем понял ее синтаксис.

1 Ответ

0 голосов
/ 26 марта 2020

Вот простая программа, которая проверяет, есть ли у каждого item эти три атрибута:

#define RAPIDJSON_HAS_STDSTRING 1
#include "rapidjson/document.h"
#include "rapidjson/istreamwrapper.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <iterator>

using namespace rapidjson;
using namespace std;

bool check_or_error(bool check, string message) {
    if (!check) {
        cerr << message << endl;
    }
    return check;
}

int main() {
    Document doc;
    {
        // This just loads JSON from a file into `doc`.
        ifstream fs("test2.json");
        IStreamWrapper isw(fs);
        doc.ParseStream(isw);
        if (doc.HasParseError()) {
            cerr << "Parse error " << doc.GetParseError() << " at " << doc.GetErrorOffset();
            exit(1);
        }
    }

    // Grab the element under `item` and coerce it to an array.
    const Value::Array& a = doc["item"].GetArray();
    // This is a standard iterator pattern; we set `it` equal to every element
    // in turn. We use `cbegin`/`cend` to get const iterators, which do not
    // modify the array.
    for (auto it = cbegin(a); it != cend(a); it++) {
        bool ok = true;
        // Is it an object? if not, complain and move to the next element.
        ok = check_or_error(it->IsObject(), "Item is not an object");
        if (!ok) continue;

        const Value::Object& item = it->GetObject();
        int idx = std::distance(cbegin(a), it);
        static std::string mandatory[] = { "name", "attribute", "available" };
        // For every mandatory key ...
        for (const auto& key : mandatory) {
            // ... check if it is present or complain
            // The weird `(stringstream() << ...).str()` construct
            // allows us to creata formatted message as a string.
            ok = check_or_error(item.HasMember(key), (stringstream() << "item[" << idx << "] missing key " << key).str());
            if (!ok) continue;

            // ... check if it is a string or complain
            const Value& v = item[key];
            check_or_error(v.IsString(), (stringstream() << "item[" << idx << "][" << key << " not a string ").str());
        }
    }
}

Обратите внимание, что она не проверяет дубликаты ключей, поскольку Rapid JSON скрывает это для вас.

Соответствующая JSONSchema будет: ( проверить себя )

{
  "type": "object",
  "required": [
    "item",
    "category"
  ],
  "properties": {
    "item": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name",
          "attribute",
          "available"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "attribute": {
            "type": "string"
          },
          "available": {
            "type": "string"
          }
        }
      }
    },
    "category": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string"
          }
        }
      }
    }
  }
}
...