nlohmann json,与嵌套结构相互转换

nlohmann json, converting to and from nested structures

我在嵌入式项目中使用 nlohmann json (JSON for modern C++)。 OS 是猫鼬 OS。 Mongoose 有一个很好的配置系统,配置数据在 mos.yml 文件中处理和布局。该文件在构建时被转换为结构和访问函数。因此,我可以将配置数据作为结构获取,其中包含其他嵌套结构。我需要将其转换为 JSON.

我的理解是 nlohmann::json 能够将 JSON 与我自己的类型相互转换,我所要做的就是提供 to_json()from_json()此处解释的方法:

nlohmann json docs (type conversion example)

这个示例代码非常简单:

struct person {
    std::string name;
    std::string address;
    int age;
};

void to_json(json& j, const person& p) {
    j = json{{"name", p.name}, {"address", p.address}, {"age", p.age}};
}

但是给出的例子非常简单。我的类型更复杂,我无法弄清楚更复杂结构的语法,比如这个(为简洁起见摘录):

struct mgos_config_mytype {
  struct mgos_config_mytype_input input;
  struct mgos_config_mytype_speed speed;

  /* many others omitted */

};

struct mgos_config_mytype_input {
  struct mgos_config_mytype_input_wired_buttons wired_buttons;
};

struct mgos_config_mytype_input_wired_buttons {
  const char * btn1;
  const char * btn2;
  const char * btn3;
};

如果有人能告诉我它是如何完成的或指出正确的方向,我将不胜感激,谢谢。

这是一个嵌套类型的示例,其中 to_json 定义为统一类型 Person (live):

#include <iostream>
#include <string>

#include <nlohmann/json.hpp>
using nlohmann::json;

struct Name
{
    std::string first;
    std::string last;
};

struct Address
{
    std::string houseNo;
    std::string street;
    std::string city;
    std::string postalCode;
    std::string country;
};

struct Person
{
    Name    name;
    Address address;
    int     age;
};

void to_json(json& j, const Person& p)
{
    j = json{
        { "name", {
            { "first", p.name.first },
            { "last", p.name.last }
            } 
        },
        { "address", {
            { "house", p.address.houseNo },
            { "street", p.address.street },
            { "city", p.address.city },
            { "postal_code", p.address.postalCode },
            { "country", p.address.country }
            }
        },
        { "age", p.age}
    };
}

int main()
{
    const Person p { 
        { "firstname", "lastname" }, 
        { "123", "St. ABC", "XYZ", "123456", "country" }, 
        18
    };

    json j { p };
    std::cout << j.dump(4) << '\n';

    return 0;
}

输出:

[
    {
        "address": {
            "city": "XYZ",
            "country": "country",
            "house": "123",
            "postal_code": "123456",
            "street": "St. ABC"
        },
        "age": 18,
        "name": {
            "first": "firstname",
            "last": "lastname"
        }
    }
]

根据嵌套类型的复杂性和可重用性,您可以为所有类型定义 to_jsonfrom_json

这是个人对JSON和JSON个人的例子(live):

#include <iostream>
#include <string>

#include <nlohmann/json.hpp>
using nlohmann::json;

struct Name
{
    std::string first;
    std::string last;
};

struct Address
{
    std::string houseNo;
    std::string street;
    std::string city;
    std::string postalCode;
    std::string country;
};

struct Person
{
    Name    name;
    Address address;
    int     age;
};

void to_json(json& j, const Name& name)
{
    j = json{
        { "first", name.first },
        { "last", name.last }
    };
}

void from_json(const json& j, Name& name)
{
    j.at("first").get_to(name.first);
    j.at("last").get_to(name.last);
}

void to_json(json& j, const Address& address)
{
    j = json{
        { "house", address.houseNo },
        { "street", address.street },
        { "city", address.city },
        { "postalCode", address.postalCode },
        { "country", address.country }
    };
}

void from_json(const json& j, Address& address)
{
    j.at("house").get_to(address.houseNo);
    j.at("street").get_to(address.street);
    j.at("street").get_to(address.street);
    j.at("city").get_to(address.city);
    j.at("postalCode").get_to(address.postalCode);
    j.at("country").get_to(address.country);
}

void to_json(json& j, const Person& p)
{
    j = json{
        { "name", p.name },
        { "address", p.address },
        { "age", p.age }
    };
}

void from_json(const json& j, Person& p)
{
    j.at("name").get_to(p.name);
    j.at("address").get_to(p.address);
    j.at("age").get_to(p.age);
}

int main()
{
    const Person p1 { 
        { "firstname", "lastname" }, 
        { "123", "St. ABC", "XYZ", "123456", "country" }, 
        18
    };

    const json j1 { p1 };               // Get JSON object from Person
    const auto s1 = j1.dump(4);         // Get JSON string with indentation (4 spaces)
    std::cout << s1 << '\n';

    auto p2 = j1[0].get<Person>();      // Get Person object from JSON array
    p2.name = { "ABC", "XYZ" };         // Update first and last names

    const json j2 { p2 };               // Get JSON object from Person
    const auto s2 = j2.dump(4);         // Get JSON string with indentation (4 spaces)
    std::cout << s2 << '\n';


    return 0;
}

输出:

[
    {
        "address": {
            "city": "XYZ",
            "country": "country",
            "house": "123",
            "postalCode": "123456",
            "street": "St. ABC"
        },
        "age": 18,
        "name": {
            "first": "firstname",
            "last": "lastname"
        }
    }
]
[
    {
        "address": {
            "city": "XYZ",
            "country": "country",
            "house": "123",
            "postalCode": "123456",
            "street": "St. ABC"
        },
        "age": 18,
        "name": {
            "first": "ABC",
            "last": "XYZ"
        }
    }
]