web-dev-qa-db-ja.com

C ++クラスからJSONへの変換

クラスのインスタンス変数を含むJSON文字列を作成したいと思います。

例えば、

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

になるだろう:

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

JSONを作成するためにいくつかのC++ライブラリを調べましたが、それらはすべて非常に複雑に見えます。 JavascriptのJSON.stringify(object)に似たものが欲しい。つまり、std :: mapを渡して文字列を受け取るだけです。マップには、他のマップ、ベクター、リスト、文字列、数字、ブールを含めることができます。

これを行う最も良い方法は何ですか?

ご協力いただきありがとうございます。

編集

私は次のことを調べました:

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

以下の回答のように個別のJSONオブジェクトを構築し、JSONに変換できると理解していますが、私のものを標準コレクションに保存して変換できるようにしたいと思います。

編集2

さて、C++のリフレクションがないため不可能だと思われるため、クラスをシリアル化するという考えを捨ててください。

データ型を変更したり、データを新しいデータ型にコピーしたりせずに、std:maps、std :: vectors、std :: lists、numbers、strings、boolsを含むstd :: mapをJSONに変換する良い方法はありますか?

ありがとう。

54
tgt

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();

出力:

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

json_map_demo.cpp は、開始するのに良い場所だと思います。

24
sehe

優れたC++ JSONライブラリはこれを行う必要があり、そうでないことを見るのは悲しいです- ThorsSerializer と明らかに Nosjob を除いて 質問

もちろん、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);

使用例:

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);
}

ランニング:

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

C++ではこれ以上のことはできません。

16
Sebastian

あなたの問題を解決するために設計されたライブラリを書きました。しかし、それは非常に新しいプロジェクトであり、十分に安定していません。ホームページをご覧ください::

https://github.com/Mizuchi/acml

この例では、次のように1行追加する必要があります。

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

どのメンバーをダンプするかをライブラリに伝えるため。 C++にはリフレクションがないため。また、メンバーにアクセスする方法を提供する必要があります。公開メンバーレベルを使用するか、フレンドクラスを使用します。

そして、後で次のように実行する必要があります。

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

次のようになります::

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

ご覧のとおり、JSON配列はまだ実装されていません。そして今、すべてが文字列になります。

4
ytj

マップまたはオブジェクトをJSON化しますか? (あなたの例はクラスを示していますが、マップを言っています)。マップについては、このライブラリを確認してください- JSON Spirit

オブジェクトの場合:C++にはリフレクションがサポートされていない(非常に限られたRTTIを除く)ため、シリアル化のための「ワンクリック」ソリューションもありません。どのソリューションでも、シリアライズおよびデシリアライズするクラスに追加の、おそらく密結合されたコードを記述する必要があります(非公開データをシリアライズするかどうかによって異なります)。

4
Tamás Szelei

シリアル( http://uscilab.github.io/cereal/ )を見ましたか? C++を使用してJSONとの間でシリアル化するJSONアーカイブがあります。

(シリアルからの)オーバーヘッドが最小の例は、SOにあります: https://stackoverflow.com/a/22587527/255635

2
Robert

私は仕事をすることができる実験的なライブラリを書きましたが、クラスの構造と階層の外部記述が必要です。 GCCXMLを使用して、シリアル化と逆シリアル化に使用されるxml辞書を作成します。

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

今のところ、基本的な型(int、float double)、基本的な型へのポインター、クラス、継承されたメンバーなどを扱うことができる実験的なプロジェクトです... std :: stringインスタンス。

実装の詳細を参照してください こちら

1
JBV06

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;
}

出力:

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