Skip to content

Latest commit

 

History

History
184 lines (137 loc) · 7.72 KB

SaveLoad_json.md

File metadata and controls

184 lines (137 loc) · 7.72 KB

Save and load : json

Third-party library

The third party library used is GitHub - nlohmann/json: JSON for Modern C++. The single header json.hpp is used and can be found in the folder /thirdParty/json of the Glove repository. Of course, it is also possible to use the json.hpp of the json repository.

When using the single header glove.h (option 1), the json management is disabled by default. The macro #define GLOVE_ENABLE_JSON must be defined before #include "glove.h".

When using the Glove library from the installed includes and built libraries (option 2), the json management is enabled by default. The file json.hpp is also part of the installed third party libraries. So by default the json management is operational.

Introduction

As an extension of the save/load interface introduced here, it is possible to save and load a parametrization using the json formating.

This extension applies only on GlvParametrizationWidget, using the parameters name and value as json fields and values.

The following types and containers are managed by default by the json library:

  • arithmetic types

  • enum

  • std::string

  • std::vector

  • std::map

Example

Let us consider two simple parametrizations ClassA and ClassB :

glvm_parametrization(ClassB, "ClassB",
                                        paramA, int, "paramA", "comment about parameterA", 0,
                                        paramB, float, "paramB", "comment about parameter B", 0.f,
                                        paramC, bool, "paramC", "comment about parameter C", true,
                                        paramD, std::vector<double>, "paramD", "comment about parameter D", {7.},
                                        paramE, std::string, "paramE", "comment about parameter E", "default")
glvm_parametrization(ClassA, "ClassA",
                                        paramA, int, "paramA", "comment about parameterA", 0,
                                        paramB, float, "paramB", "comment about parameter B", 0.f,
                                        paramC, bool, "paramC", "comment about parameter C", true,
                                        paramD, std::vector<double>, "paramD", "comment about parameter D", std::vector<double>({5., 9.},
                                        paramE, std::string, "paramE", "comment about parameter E", "default",
                                        paramF, ClassB, "paramF", "comment about parameter F", ClassB())
GlvParametrizationWidget<ClassA>* param_widget = new GlvParametrizationWidget<ClassA>;
GlvParametrizationSaveLoad<ClassA>* save_load_widget = new GlvParametrizationSaveLoad<ClassA>(param_widget);
param_widget->show();

The obtained parametrization widget is shown below.

sample009-3

Using Save:

sample009-3

and applying .json extension, we obtain the following json file. The file can be modified and loaded back for instance.

{
    "ClassA": {
        "paramA": 0,
        "paramB": 0.0,
        "paramC": true,
        "paramD": [
            5.0,
            9.0
        ],
        "paramE": "default",
        "paramF": {
            "ClassB": {
                "paramA": 0,
                "paramB": 0.0,
                "paramC": true,
                "paramD": [
                    7.0
                ],
                "paramE": "default"
            }
        }
    }
}

More details and examples can be found in sample009_1.cpp.

Specific json for other types

Types that are not managed by default by the json library must have their parsing implemented. You can either specialize read and write functions, or implement methods (if the type is a class you can modify). Let us consider a class ClassTest:

class ClassTest {
    int value;
public:
    ClassTest(int _value = 2) { value = _value; }
    ~ClassTest() {}
    int get_value() const { return value;}
    void set_value(const int _value) { value = _value; }
    bool readB(std::ifstream& _input_file) {
        return slv::rw::readB(value, _input_file);
    }
    void writeB(std::ofstream& _output_file) const {
        slv::rw::writeB(value, _output_file);
    }

    friend std::ostream& operator<<(std::ostream& _os, const ClassTest& _test) {
        _os << _test.value;
        return _os;
    }
    friend std::istream& operator>>(std::istream& _is, ClassTest& _test) {
        _is >> _test.value;
        return _is;
    }

    void writeJson(nlohmann::json& _json) const {
        _json = value;
    }
    SlvStatus readJson(const nlohmann::json& _json) {
        value = _json.get<int>();
        return SlvStatus();
    }
};

a specialization of read and write functions such as:

template <>
void slv::rw::json::writeJson_spec<ClassTest>(const ClassTest& _test, nlohmann::json& _json) {
    _json = _test.get_value();
}

template <>
SlvStatus slv::rw::json::readJson_spec<ClassTest>(ClassTest& _test, const nlohmann::json& _json) {
    _test.set_value(_json.get<int>());
    return SlvStatus();
}

and a parametrization such as:

glvm_parametrization(ClassA, "ClassA",
                                        paramA, int, "paramA", "comment about parameterA", 0,
                                        paramB, float, "paramB", "comment about parameter B", 0.f,
                                        paramC, bool, "paramC", "comment about parameter C", true,
                                        paramD, std::vector<double>, "paramD", "comment about parameter D", {},
                                        paramE, std::string, "paramE", "comment about parameter E", "default",
                                        paramF, ClassTest, "paramF", "comment about parameter F", ClassTest())

When showing the corresponding parametrization widget, the Save/Load buttons will propose the json parsing by showing the .json extension. The parser used here will be the specialization of slv::rw::json::writeJson_spec and slv::rw::json::readJson. Indeed, several options exist for the json save/load option to be enabled. The functions/methods enabling it are (by priority order of their actual use if available together):

  • Specialize writeJson_spec and readJson_spec

  • Implement writeJson and readJson methods

  • Implement ofstream and ifstream methods (see this page)

  • Implement ostream and istream methods (see this page)

  • Implement << / >> operators

If any of the implementation is available, json save/load will be proposed.

More details and examples can be found in sample009_2.cpp.

Remark 1

Save/load of parametrization using json requires all the involved types (recursively) to be managed. If one type does not have both read and write possibilities (i.e. a full line of the list above), the the .json option of the Save/Load buttons will be disabled.

Remark 2

Unlike the binary parser described here, the lack of methods for json parsing will not produce compilation errors. It means that as long as both slv::rw::writeB and slv::rw::readB are properly specialized or both writeB and readB methods are implemented (this is the case for ClassTest), using:

GlvParametrizationSaveLoad<ClassA>* save_load_widget = new GlvParametrizationSaveLoad<ClassA>(param_widget);