3

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

我的理解是 nlohmann::json 能够将 JSON 转换为我自己的类型,我所要做的就是提供to_json()from_json()方法,如下所述:

nlohmann json docs(类型转换示例)

此示例代码非常简单:

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;
};

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

4

1 回答 1

6

to_json这是一个为合并类型Personlive )定义的嵌套类型的示例:

#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

这是 Person-to-JSON 和 JSON-to-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 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"
        }
    }
]
于 2020-05-10T08:24:54.920 回答