将 C++ 类转换为 JSON

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8220130/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:11:55  来源:igfitidea点击:

Converting C++ class to JSON

c++jsonserialization

提问by tgt

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

我想创建一个包含我的类的实例变量的 JSON 字符串。

For example,

例如,

class Example {  
    std::string string;  
    std::map<std::string, std:string> map;  
    std::vector<int> vector;  
};

would become:

会成为:

{
    "string":"the-string-value",
    "map": {
        "key1":"val1",
        "key2":"val2"
    },
    "vector":[1,2,3,4]
}

I've looked into several C++ libraries for creating JSON and they all seem incredibly complex. I'd like something similar to Javascript's JSON.stringify(object). In other words just pass a std::map to it and receive a string. The map could contain other maps, vectors, lists, strings, numbers and bools.

我研究了几个用于创建 JSON 的 C++ 库,它们看起来都非常复杂。我想要类似于 Javascript 的JSON.stringify(object). 换句话说,只需将 std::map 传递给它并接收一个字符串。地图可以包含其他地图、向量、列表、字符串、数字和布尔值。

What's the nicest way to do this?

什么是最好的方法来做到这一点?

Thanks for your help.

谢谢你的帮助。

Edit

编辑

I've looked into the following:

我研究了以下内容:

json spirit, jsoncpp, zoolib, JOST, CAJUN, libjson, nosjob, JsonBox, jsonme--

json精神、jsoncpp、zoolib、JOST、CAJUN、libjson、nosjob、JsonBox、jsonme--

Which I understand I can construct a separate JSON object as in an answer below and convert to JSON I'd like to be able to store my stuff in standard collections and convert.

我知道我可以像下面的答案一样构造一个单独的 JSON 对象并转换为 JSON 我希望能够将我的东西存储在标准集合中并进行转换。

Edit 2

编辑 2

Okay, scrap the idea of serializing a class since it appears that's impossible with C++'s lack of reflection.

好吧,放弃序列化类的想法,因为 C++ 缺乏反射,这似乎是不可能的。

Is there a nice way to convert a std::map containing std:maps, std::vectors, std::lists, numbers, strings, and bools to JSON without having to change datatypes or copying data to a new datatype?

是否有一种很好的方法可以将包含 std::maps、std::vectors、std::lists、数字、字符串和 bool 的 std::map 转换为 JSON,而无需更改数据类型或将数据复制到新的数据类型?

Thanks.

谢谢。

采纳答案by sehe

JSON Spiritwould allow you to do it like so:

JSON Spirit允许你这样做:

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.cppwould be a nice place to start, I suppose.

json_map_demo.cpp将是一个不错的地方开始,我想。

回答by Sebastian

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

任何好的 C++ JSON 库都应该这样做,很遗憾看到他们没有这样做——除了ThorsSerializer和这个问题中提到的显然Nosjob

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

当然,C++ 不像 Java 那样有反射,所以你必须显式地注释你的类型:(
从 ThorsSerializer 文档中复制)

#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++.

在 C++ 中你不能做得比这更好。

回答by Tamás Szelei

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.

您想对地图或对象进行 JSON 化吗?(你的例子显示了一个类,但你说的是一张地图)。如需地图,请查看此库 - 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).

对于对象:C++ 中没有反射支持(除了非常有限的 RTTI),因此也没有“一键式”序列化解决方案。任何解决方案都需要您为要序列化和反序列化的类编写额外的、可能是紧密耦合的代码(这取决于您是否要序列化非公共数据)。

回答by ytj

I wrote a library which designed to solve your problem. However, it is a very new project, not stable enough. Feel free to take a look, the homepage is here::

我写了一个旨在解决您的问题的库。但是,它是一个非常新的项目,不够稳定。随意看看,主页在这里::

https://github.com/Mizuchi/acml

https://github.com/Mizuchi/acml

In your example, you have to add one line like this:

在您的示例中,您必须像这样添加一行:

ACML_REGISTER(Example, ,(string)(map)(vector));

in order to tell the library which member you want to dump. Since C++ have no reflection. And you must give a way to access the member, either use public member level or use friend class.

为了告诉图书馆你想转储哪个成员。由于 C++ 没有反射。并且您必须提供一种访问成员的方法,使用公共成员级别或使用朋友类。

And later you just need to do sth like this:

后来你只需要这样做:

string result = acml::json::dumps(any_object);

字符串结果 = acml::json::dumps(any_object);

would become::

会成为::

{
    "string": "the-string-value",
    "map":
    {
        "key1": "val1",
        "key2": "val2"
    },
    "vector":
    {
        "type": "std::vector",
        "size": "4",
        "0": "1",
        "1": "2",
        "2": "3",
        "3": "4"
    }
}

As you see, JSON array is not implemented yet. And everything becomes string now.

如您所见,JSON 数组尚未实现。现在一切都变成了字符串。

回答by Robert

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

你看过麦片(http://uscilab.github.io/cereal/)吗?它具有使用 C++ 序列化到/从 JSON 的 JSON 档案。

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

可以在 SO 上找到一个开销最小的示例(来自谷物):https: //stackoverflow.com/a/22587527/255635

回答by JBV06

I have written an experimental library that can do the job, but it requires external description of classes structures and hierarchy. It uses GCCXML to build an xml dictionary, used for serialization de-serialization :

我编写了一个可以完成这项工作的实验库,但它需要类结构和层次结构的外部描述。它使用 GCCXML 构建一个 xml 字典,用于序列化反序列化:

http://code.google.com/p/cjson/

http://code.google.com/p/cjson/

It's for the moment an experimental project, that can deals with fundamental types (int, float double), pointers to fundamentals types, classes, inherited members etc ... It implements basic std::vector ans std::map serialization, and also std::string instances.

目前这是一个实验项目,可以处理基本类型(int、float double)、指向基本类型、类、继承成员等的指针......它实现了基本的 std::vector ans std::map 序列化,以及std::string 实例。

See details for implementation here

在此处查看实施详情

回答by mect

You could use Boost.PropertyTree.

你可以使用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"
    ]
}

回答by kcris

thispython script generates c++ pod classes with one member for each json property

这个python脚本为每个json属性生成一个成员的c++ pod类

you want quite the opposite thing, but is trivial to generate a mapping class which does both loading and saving

你想要完全相反的东西,但是生成一个同时加载和保存的映射类是微不足道的

generated code relies on an external json parser library

生成的代码依赖于外部 json 解析器库

回答by kola

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

如果问题仍然存在,请查看json_dto库,这是一个用于在 JSON 表示和 C++ 结构之间转换数据的小型头文件助手。

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_dtoyou can create the following JSON:

json_dto的帮助下,您可以创建以下 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.

给定这样的 JSON 字符串,您可以将其转换为结构。