Converting C++ class to JSON

前端 未结 11 855
轮回少年
轮回少年 2020-12-02 11:56

I\'d like to create a JSON string containing the instance variables of my class.

For example,

class Example {  
    std::string string;  
    std::ma         


        
相关标签:
11条回答
  • 2020-12-02 12:25

    You could use Boost.PropertyTree.

    #include <map>
    #include <vector>
    #include <string>
    #include <iostream>
    #include <boost/property_tree/ptree.hpp>
    #include <boost/property_tree/json_parser.hpp>
    
    namespace pt = boost::property_tree;
    
    int main() {
        // Create an empty property tree object.
        pt::ptree tree;
    
        // Put a string value into the tree.
        tree.put("string", "the-string-value");
    
        // Put a map object into the tree.
        pt::ptree child1;
        std::map<std::string, std::string> map = {{"key1", "val1"},
                                                  {"key2", "val2"}};
        for (auto &p : map) {
            child1.add(p.first, p.second);
        }
        tree.add_child("map", child1);
    
        // Put a vector of numbers into the tree
        pt::ptree child2;
        std::vector<int> vector = {1, 2, 3, 4};
        for (auto &v : vector) {
            pt::ptree item;
            item.put("", v);
            child2.push_back(std::make_pair("", item));
        }
        tree.add_child("vector", child2);
    
        // Write property tree to JSON file
        pt::write_json("output.json", tree);
    
        return 0;
    }
    

    Output:

    {
        "string": "the-string-value",
        "map": {
            "key1": "val1",
            "key2": "val2"
        },
        "vector": [
            "1",
            "2",
            "3",
            "4"
        ]
    }
    
    0 讨论(0)
  • 2020-12-02 12:27

    JSON Spirit would allow you to do it like so:

    Object addr_obj;
    
    addr_obj.push_back( Pair( "house_number", 42 ) );
    addr_obj.push_back( Pair( "road",         "East Street" ) );
    addr_obj.push_back( Pair( "town",         "Newtown" ) );
    
    ofstream os( "address.txt" );
    os.write( addr_obj, os, pretty_print );
    os.close();
    

    Output:

    {
        "house_number" : 42,
        "road" : "East Street",
        "town" : "Newtown"
    }
    

    The json_map_demo.cpp would be a nice place to start, I suppose.

    0 讨论(0)
  • 2020-12-02 12:29

    Have you looked at cereal (http://uscilab.github.io/cereal/) ? It has JSON archives for serializing to/from JSON using C++.

    An example with minimal overhead (from cereal) can be found here on SO: https://stackoverflow.com/a/22587527/255635

    0 讨论(0)
  • 2020-12-02 12:31

    Do you want to JSON-ify a map or an object? (your example shows a class, yet you say a map). For a map, check out this library - JSON Spirit.

    For objects: There is no reflection support in C++ (apart from the very limited RTTI), so there is no "one-click" solution for serialization either. Any solution will require you to write additional, possibly tightly coupled code to the class you want to serialize and de-serialize (that depends on if you want to serialize non-public data).

    0 讨论(0)
  • 2020-12-02 12:32

    Any good C++ JSON library should do this and it is sad to see that they don't -- with the exception of ThorsSerializer and apparently Nosjob as mentioned in this question.

    Of course, C++ does not have reflection like Java, so you have to explicitly annotate your types:
    (copied from the ThorsSerializer documentation)

    #include "ThorSerialize/JsonThor.h"
    #include "ThorSerialize/SerUtil.h"
    #include <map>
    #include <vector>
    #include <string>
    #include <iostream>
    
    class Example {
        std::string string;
        std::map<std::string, std::string> map;
        std::vector<int> vector;
    
        // Allow access to the class by the serialization library.
        friend class ThorsAnvil::Serialize::Traits<Example>;
    
        public:
            Example(std::string const& s, std::map<std::string, std::string> const& m, std::vector<int> const& v)
                : string(s), map(m), vector(v)
            {}
    };
    
    // Define what members need to be serilizable
    ThorsAnvil_MakeTrait(Example, string, map, vector);
    

    Example Usage:

    int main()
    {
        using ThorsAnvil::Serialize::jsonExport;
        using ThorsAnvil::Serialize::jsonImport;
    
    
        Example     e1 {"Some Text", {{"ace", "the best"}, {"king", "second best"}}, {1 ,2 ,3, 4}};
    
        // Simply serialize object to json using a stream.
        std::cout << jsonExport(e1) << "\n";
    
        // Deserialize json text from a stream into object.
        std::cin  >> jsonImport(e1);
    }
    

    Running:

    {
        "string": "Some Text",
        "map":
        {
            "ace": "the best",
            "king": "second best"
        },
        "vector": [ 1, 2, 3, 4]
    }
    

    You cannot do better than this in C++.

    0 讨论(0)
  • 2020-12-02 12:33

    If the question is still actual, then look at json_dto library, a small header-only helper for converting data between JSON representation and c++ structs.

    For example having the following structs:

    struct message_source_t
    {
      // Worker thread.
      std::int32_t m_thread_id;
    
      // Sender.
      std::string m_subsystem;
    };
    
    struct message_t
    {
      // Who sent a message.
      message_source_t m_from;
    
      // When the message was sent (unixtime).
      std::tm m_when;
    
      // Message text.
      std::string m_text;
    };
    

    with the help of json_dto you can create the following JSON:

    {
      "from" : 
        {
          "thread_id" : 4242,
          "sybsystem" : "json_dto"
        },
      "when" : "2016.09.28 19:55:00",
      "text" : "Hello world!"
    }  
    

    And given such JSON string you can convert it to structs.

    0 讨论(0)
提交回复
热议问题