如何在 C++ 中创建类似 nlohaman::json 的结构

问题描述 投票:0回答:1

我想创建一个像 nlohaman::json 的结构。 nlohaman;:json 结构的神奇之处在于它几乎可以容纳任何类型的数据,它的美妙之处在于你不需要调用任何愚蠢的函数来获取你的值。

这就是我的意思,


#include <iostream>

#include <string>

#include "nlohmann/json.hpp"



using namespace std;



int main(int argc, char *argv[])

{

    nlohmann::json obj; 



obj["string"] = "key";



cout<<obj["j"]<<"\n"; 

obj["hobbies"] = {"Reading", "Gaming", "Traveling"};

for (auto &it: obj["hobbies"])
{
cout<<it<<"\n";
}

    return 0;

}


如果您观察到此结构的三个优点是。

  1. 您几乎可以存储任何类型的数据。
  2. 您可以像在 JavaScript 中一样通过输入键名称来获取数据,无需使用
    std::get<std::string>(obj["string"])
    从变体(或任何类型的值)中获取字符串值。
  3. 您不需要显式调用 union、struct 或任何内部使用的构造函数来保存这样的数据,
    obj["key"] = structName("value");

我正在尝试从一周开始创建一个这样的结构。 我尝试用联合、变体、结构创建这种结构,但没有一个是这样的。

看看我的一些实现。

#include <iostream>


#include <string>


#include <vector>


#include <map>


#include <vector>


#include <variant>


using namespace std;



// This one directly stores values 



union val2 {

    
    string s; 


    vector<string> v;


    val2(const string &c) : s(c) {}


    val2(const char *c) : s(c) {}

    
    val2(const initializer_list<string> & z): v(z){}


    ~val2(){}

    

    
};

//This one stores pointer approach 



union val {

    string *v;


    vector<string> *g;


    val(const string &c) : v(new string(c)) {}


    val(const char *c) : v(new string(c)) {}
    val(const initializer_list<string> & z): g(new vector<string>(z)){}
    val(const vector<string> & d) : g(new vector<string>(d)){}











    





    val(const val &other)


    {

        
        if (other.v != nullptr)

        
        {

            
            v = new string(*other.v);

        
        }

        
        else if (other.g != nullptr)

       {

            
            g = new vector<string>(*other.g);
        }


   }

    ~val() {}

};





int main(int argc, char *argv[]


{

    
       vector<val> v = {


        "gh",


        "u",


        {"f", "d"}

    };

    


    vector<val2> n= 


    {

        
            "g", 
            "h",
            {"6"}


    };


    cout << *v[0].v << "\n";

    


    cout<<n[2].v[0]<<"\n";

    


    return 0;


}

如您所见,要获取字符串,我需要使用并集的 .s,向量的 .v。我在变体中实现了相同的结构,但我们再次需要使用

std::get<std::string>
来获取字符串,同样对于向量,我们需要使用
std::get<vector<std::string>(obj["v"])

告诉我其中哪一篇对您来说更具可读性。

//One with variant approach 

std::vector<std::string> v = std::get<std::vector<std::string>>(obj["v"]);

//One with nlohaman json approach   


std::vector<std::string> v = obj["v"];

我猜你更喜欢第二种方法。

我想创建类似的结构,所以如果你们中有人知道如何做到这一点,请回答这个问题。 预先感谢您的回答。

c++ templates data-structures nlohmann-json
1个回答
0
投票

obj["v"];
正在调用一个“愚蠢的函数”。它称为
operator[]
。如果您想要的话,您也可以超载
operator[]

无论如何,您可以使用

std::any
并将转换隐藏在模板化转换运算符中:

#include <any>

struct my_any {
    std::any value;
    template <typename T> my_any& operator=(const T& t) { value = t; return *this;}

    template <typename T> operator T() {
        return std::any_cast<T>(value);
    }
};


int main() {
    //std::any x  = 42;
    //int y = x; // Error, needs a cast
    my_any foo;
    foo = 42;
    int x = foo; // OK uses the template conversion operator
}

这只是最基本的说明基础知识的骨架。仍然缺少适当的构造函数等。

© www.soinside.com 2019 - 2024. All rights reserved.