zoukankan      html  css  js  c++  java
  • nlohmann 最优秀的C++序列化工具库 详细入门教程

    本文首发于个人博客https://kezunlin.me/post/f3c3eb8/,欢迎阅读最新内容!

    tutorial to use nlohmann json for serializing data with modern cpp

    Guide

    include

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

    compile with

    -std=c++11

    CMakeLists.txt

    # CMakeLists.txt
    find_package(nlohmann_json 3.2.0 REQUIRED)
    ...
    add_library(foo ...)
    ...
    target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
    

    Usage

    json demo

    {
      "pi": 3.141,
      "happy": true,
      "name": "Niels",
      "nothing": null,
      "answer": {
        "everything": 42
      },
      "list": [1, 0, 2],
      "object": {
        "currency": "USD",
        "value": 42.99
      }
    }
    

    with code

    // create an empty structure (null)
    json j;
    
    // add a number that is stored as double (note the implicit conversion of j to an object)
    j["pi"] = 3.141;
    
    // add a Boolean that is stored as bool
    j["happy"] = true;
    
    // add a string that is stored as std::string
    j["name"] = "Niels";
    
    // add another null object by passing nullptr
    j["nothing"] = nullptr;
    
    // add an object inside the object
    j["answer"]["everything"] = 42;
    
    // add an array that is stored as std::vector (using an initializer list)
    j["list"] = { 1, 0, 2 };
    
    // add another object (using an initializer list of pairs)
    j["object"] = { {"currency", "USD"}, {"value", 42.99} };
    
    // instead, you could also write (which looks very similar to the JSON above)
    json j2 = {
      {"pi", 3.141},
      {"happy", true},
      {"name", "Niels"},
      {"nothing", nullptr},
      {"answer", {
        {"everything", 42}
      }},
      {"list", {1, 0, 2}},
      {"object", {
        {"currency", "USD"},
        {"value", 42.99}
      }}
    };
    

    serialization

    // create object from string literal
    json j = "{ "happy": true, "pi": 3.141 }"_json;
    
    // or even nicer with a raw string literal
    auto j2 = R"(
      {
        "happy": true,
        "pi": 3.141
      }
    )"_json;
    
    // parse explicitly
    auto j3 = json::parse("{ "happy": true, "pi": 3.141 }");
    
    
    // explicit conversion to string
    std::string s = j.dump();    // {"happy":true,"pi":3.141}
    
    // serialization with pretty printing
    // pass in the amount of spaces to indent
    std::cout << j.dump(4) << std::endl;
    // {
    //     "happy": true,
    //     "pi": 3.141
    // }
    

    read from file/save to file

    // read a JSON file
    std::ifstream i("file.json");
    json j;
    i >> j;
    
    // write prettified JSON to another file
    std::ofstream o("pretty.json");
    o << std::setw(4) << j << std::endl;
    

    Arbitrary types conversions

    namespace ns {
        // a simple struct to model a person
        struct person {
            std::string name;
            std::string address;
            int age;
        };
    }
    

    normal method

    ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
    
    // convert to JSON: copy each value into the JSON object
    json j;
    j["name"] = p.name;
    j["address"] = p.address;
    j["age"] = p.age;
    
    // ...
    
    // convert from JSON: copy each value from the JSON object
    ns::person p {
        j["name"].get<std::string>(),
        j["address"].get<std::string>(),
        j["age"].get<int>()
    };
    

    better method

    using nlohmann::json;
    
    namespace ns {
        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);
        }
    } // namespace ns
    
    
    // create a person
    ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60};
    
    // conversion: person -> json
    json j = p;
    
    std::cout << j << std::endl;
    // {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
    
    // conversion: json -> person
    auto p2 = j.get<ns::person>();
    
    // that's it
    assert(p == p2);
    

    That's all! When calling the json constructor with your type, your custom to_json method will be automatically called. Likewise, when calling get<your_type>() or get_to(your_type&), the from_json method will be called.

    How do I convert third-party types?

    namespace nlohmann {
    
    template <typename T>
    struct adl_serializer {
        static void to_json(json& j, const T& value) {
            // calls the "to_json" method in T's namespace
        }
    
        static void from_json(const json& j, T& value) {
            // same thing, but with the "from_json" method
        }
    };
    
    }
    

    How can I use get() for non-default constructible/non-copyable types?

    struct move_only_type {
        move_only_type() = delete;
        move_only_type(int ii): i(ii) {}
        move_only_type(const move_only_type&) = delete;
        move_only_type(move_only_type&&) = default;
    
        int i;
    };
    
    namespace nlohmann {
        template <>
        struct adl_serializer<move_only_type> {
            // note: the return type is no longer 'void', and the method only takes
            // one argument
            static move_only_type from_json(const json& j) {
                return {j.get<int>()};
            }
    
            // Here's the catch! You must provide a to_json method! Otherwise you
            // will not be able to convert move_only_type to json, since you fully
            // specialized adl_serializer on that type
            static void to_json(json& j, move_only_type t) {
                j = t.i;
            }
        };
    }
    

    examples

    #pragma once
    
    #include <nlohmann/json.hpp>
    using json = nlohmann::json;
    #include "sensor_data.h"
    #include "rfid_info.h"
    
    namespace nlohmann {
    	template <>
    	struct adl_serializer<SensorData> {
    		// note: the return type is no longer 'void', and the method only takes
    		// one argument
    		static SensorData from_json(const json& j) {
    			SensorData sensor_data;
    			sensor_data.sensor_identify = j.at("SensorIdentify").get<string>();
    			return sensor_data;
    		}
    
    		// Here's the catch! You must provide a to_json method! Otherwise you
    		// will not be able to convert move_only_type to json, since you fully
    		// specialized adl_serializer on that type
    		static void to_json(json& j, SensorData t) {
    			j = json{ {"SensorIdentify",t.sensor_identify},{"SensorType",t.sensor_type },{"Data",t.data} };
    		}
    	};
    	template <>
    	struct adl_serializer<RfidInfo> {
    		// note: the return type is no longer 'void', and the method only takes
    		// one argument
    		static RfidInfo from_json(const json& j) {
    			RfidInfo rfid_info;
    			rfid_info.identify = j.at("Identify").get<string>();
    			return rfid_info;
    		}
    
    		// Here's the catch! You must provide a to_json method! Otherwise you
    		// will not be able to convert move_only_type to json, since you fully
    		// specialized adl_serializer on that type
    		static void to_json(json& j, RfidInfo t) {
    			j = json{ { "Identify",t.identify },{ "Position",0 } };
    		}
    	};
    }
    

    Binary formats(BSON...)

    // create a JSON value
    json j = R"({"compact": true, "schema": 0})"_json;
    
    // serialize to BSON
    std::vector<std::uint8_t> v_bson = json::to_bson(j);
    
    // 0x1B, 0x00, 0x00, 0x00, 0x08, 0x63, 0x6F, ...
    
    // roundtrip
    json j_from_bson = json::from_bson(v_bson);
    

    Reference

    History

    • 20191012: created.

    Copyright

  • 相关阅读:
    确认端口占用
    [转]自建Syncthing中继服务器(私密传输或造福大众)
    【转】Syncthing – 数据同步利器---自己的网盘,详细安装配置指南,内网使用,发现服务器配置
    【转】搭建和配置Syncthing发现和中继服务器
    【转】Syncthing的安装与使用
    pycrypto安装出错的问题 intmax_t C:Program Files (x86)Windows Kits10include10.0.10240.0ucrtinttypes.
    Git从库中移除已删除大文件
    词云图
    [转].NET 性能测试工具 -- 事件跟踪器(ETW)
    [转]ANTS Performance Profiler和ANTS Memory Profiler 使用
  • 原文地址:https://www.cnblogs.com/kezunlin/p/12058300.html
Copyright © 2011-2022 走看看