Простой «валидатор схемы» JSON с использованием JSON Patch (nlohmann: json)

Ну, на самом деле это не схема валидатора но в любом случае…

Мотивация

Я пишу библиотеку, которая представляет собой пользовательский интерфейс для работы с некоторыми электронными модулями. Каждый реальный модуль представлен в библиотеке соответствующим классом. Решил добавить возможность программировать модуль сразу с помощью config юридическое лицо. Также должна быть возможность читать текущая конфигурация из модуля. Также я хочу, чтобы пользователь мог сохранять (загружать) конфигурацию в (из) файл на диске, и эти данные должны быть удобочитаемыми и редактируемыми. Итак, я выбрал смерть JSON как объект конфигурации.

Итак, у моих классов есть следующие функции-члены:

void ReadConfig( json& config );
void WriteConfig( const json& config );

Как преимущество У меня есть полиморфный объект: мне не нужно много разных конфигураций для каждого класса.

Как недостаток ну … то же самое. Наличие такого полиморфного объекта делает невозможным проверку действий с неправильными конфигурациями во время компиляции, например, передачу конфигурации дискриминатора для программирования АЦП.

Решение

Я решил, что у любого настраиваемого модуля должна быть конфигурация по умолчанию (какая-то схема), значения которой, если таковые имеются, nullс. Например:

{
  "name": "V2718",
  "settings": {
    "inputs": [
      {
        "led_polarity": null,
        "polarity": null
      },
      {
        "led_polarity": null,
        "polarity": null
      }
    ],
    ...
}

Значит конфиг правильный тогда и только тогда, когда он может быть получен из значения по умолчанию, используя только замену nulls. Как мне это проверить? Ответ Патч JSON.

Код

Вот код (см. Validate функция-член). Каждый модуль-класс наследуется от UConfigurable абстрактный класс. Конечно, я мог бы предоставить код для Validate только функция, но я думаю, что весь заголовок более согласован.

UConfigurable.h

#ifndef V_PLUS_CONFIGURABLE_H
#define V_PLUS_CONFIGURABLE_H

#include <nlohmann/json.hpp>
#include <iostream>


namespace vmeplus
{
    using json = nlohmann::json;

    // Curiously recurring template pattern
    template <typename T>
    class UConfigurable
    {
        protected :
            static json   fDefaultConfig;

        public :
            UConfigurable() {};
            virtual ~UConfigurable() {};

            virtual void ReadConfig( nlohmann::json &config ) = 0;
            virtual void WriteConfig( const nlohmann::json &config ) = 0;

            static json GetDefaultConfig() { return fDefaultConfig; }
            static bool Validate( const json& source );
    };

    template<typename T>
    bool UConfigurable<T>::Validate( const json& source )
    {
        bool verdict = true;
        json patch = json::diff( source, fDefaultConfig );
        for( auto it = patch.begin(); it != patch.end(); ++it )
        {
            // key "op" MUST be in any patch according to
            // https://datatracker.ietf.org/doc/html/rfc6902
            // and its value MUST be one of the following
            // "add", "remove", "replace", "move", "copy", or "test"
            if( it->at("op") == "replace" )
            {
                // if "op" is "replace" then there MUST be the "value" key
                if( not (it->at("value").is_null()) )
                {
                    verdict = false;
                    break;
                }
            }
            else
            {
                verdict = false;
                break;
            }
        }
        return verdict;
    }

    void WriteConfigToFile( const json& j, const std::string& path );

    json ReadConfigFromFile( const std::string& path );
}
#endif

1 ответ
1

                    verdict = false;
                    break;
                }
            }
            else
            {
                verdict = false;
                break;
            }
        }
        return verdict;

Только return false; при обнаружении сбоя!
Затем return true; если дойдете до конца.

  • Я предпочитаю только один return в функции.

    – LRDPRDX

  • @LRDPRDX Это очень похоже на C и не очень похоже на C ++.

    – Мартин Йорк

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *