当前位置:   article > 正文

C++ 之 nlohmann::json 一个不错的json库_nlohmann官网

nlohmann官网

前言

最近在搞一个C++项目,用到了json和类的相互转化。但是c++没有反射,也没有像java一个方便的插件,没法办只能自己搞一个了。网上找了一下,发现nlohmann::json不错。已经运用到实际项目代码中,这里记录下。

下载源码

源码下载

API接口文档

解压之后,只需要包含 single_include\nlohmann\json.hpp 文件即可

示例

编译时,需要编译器支持c++11。linux中,g++ -std=c++11 ,windows中使用支持c++11的编译器

#include <iostream>
#include "D:\\single_include\\nlohmann\\json.hpp"

using json = nlohmann::json;
using namespace std;

namespace nlohmann {
    class videoinfo {
    public:
        int id;
        string name;
    };

    //json转class用到,需要自定义
    //This function is usually called by the get() function of the basic_json class (either explicitly or via the conversion operators).
    void from_json(const json& j, videoinfo& v) {
        j.at("id").get_to(v.id);
        j.at("name").get_to(v.name);
    }
    
    //class转json用到,需要自定义
    //This function is usually called by the constructors of the basic_json class.
    void to_json(json& j, const videoinfo& value){
        j = json{ {"id", value.id}, {"name",value.name} };
    }
};

int main()
{
    json j = { {"id",3},{"name","jiahui"}};
    //json转class
    auto x = m.get<nlohmann::videoinfo>();
    //class转json
    json m = x;
    //获取字符串
    string str = j.dump();
    
    std::cout << "Hello World!\n";
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

以上只演示了string和class之间的转换,如果需要其他的操作
参考这里:
官网:https://nlohmann.github.io/json/api/basic_json/
中文:https://www.cnblogs.com/linuxAndMcu/p/14503341.html#_label2_5
https://www.cnblogs.com/kezunlin/p/12058300.html

遇到的问题

1.如果字符串(json object)初始化json对象,没有得到json的object类型,依然是string。解决方法是初始化时使用迭代器。
比如:

std::string s = "{\"happy\":true,\"pi\":3.141}";
json m = json::parse(s.begin(), s.end());
  • 1
  • 2

2.如果定义的类中没有默认构造函数,那么你需要这样实现转换函数(上面的例子有默认构造函数)

namespace nlohmann
{
template <>
struct adl_serializer<nlohmann::videoinfo>
{
    static nlohmann::videoinfo from_json(const json& j)
    {
        return {j.at("id"), j.at("name")};
    }

    static void to_json(json& j, nlohmann::videoinfo p)
    {
        j["name"] = p.name;
        j["id"] = p.id;
    }
};
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3.当调用json.at()方法时注意,这个方法会抛出异常,需要处理。

4.类继承中如何使用json

class A {
public:
    A() : A_name("aaa"), A_age(10) {}
    virtual ~A(){}
    friend void to_json(nlohmann::json& j, const A e);
    friend void from_json(const nlohmann::json& j, A& e);

protected:
    //这里的属性权限为protected,应为需要子类给赋值
    string A_name;
    int    A_age;
};

void to_json(nlohmann::json& j, const A e)
{
    j = nlohmann::json{
        {"A_name", e.A_name},
        {"A_age", e.A_age}
    };
}

void from_json(const nlohmann::json& j, A& e)
{
    j.at("A_name").get_to(e.A_name);
    j.at("A_age").get_to(e.A_age);
}

class B : public A
{
public:
    B() :B_address("b_address") {}
    virtual ~B() {}

    friend void to_json(nlohmann::json& j, const B& e);
    friend void from_json(const nlohmann::json& j, B& e);
private:
    string B_address;
};

void to_json(nlohmann::json& j, const B& e)
{
    j = static_cast<A>(e);
    j["B_address"] = e.B_address;
}

void from_json(const nlohmann::json& j, B& e)
{  
    from_json(j, static_cast<A&>(e));
    j.at("B_address").get_to(e.B_address);
}

int main()
{
    string str = "{\"A_age\":3333,\"A_name\":\"1111\",\"B_address\":\"xxxx\"}";
    nlohmann::json dataJ = nlohmann::json::parse(str);

    B x;
    from_json(dataJ, x);

    B b;
    nlohmann::json j = b;

    cout << j.dump() << endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

5.编码问题
本库只支持utf-8编码格式,其他格式会报异常。

怎么处理编码转换,参考这里

6.如果你的数据结构很复杂,建议参考使用这个扩展,反射功能,无需再手动写from_jsonto_json

7.如果你的类字段为基础类型,那么可以使用库提供的注册宏,不需要自定义两个序列化函数。

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, …) 将在要为其创建代码的类/结构的命名空间内定义。
NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, …) 将在要为其创建代码的类/结构中定义。 该宏还可以访问私有成员。

举例:

class A {
public:
    A() : A_name("aaa"), A_age(10) {}
    virtual ~A(){}

	NLOHMANN_DEFINE_TYPE_INTRUSIVE(A, A_name, A_age);
protected:
    //这里的属性权限为protected,应为需要子类给赋值
    string A_name;
    int    A_age;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/601180
推荐阅读
相关标签
  

闽ICP备14008679号