72

ブースト プロパティ ツリーを使用して JSON 配列を作成しようとしています。

ドキュメントには、「JSON 配列はノードにマップされます。各要素は、名前が空の子ノードです」と記載されています。

write_json(...)したがって、空の名前でプロパティ ツリーを作成し、呼び出して配列を取り出したいと思います。ただし、ドキュメントには、名前のない子ノードを作成する方法が記載されていません。を試しptree.add_child("", value)ましたが、これにより次の結果が得られます。

Assertion `!p.empty() && "Empty path not allowed for put_child."' failed

ドキュメントは、少なくとも私が理解できる方法では、この点に対処していないようです。誰でも助けることができますか?

4

7 に答える 7

119

単純な配列:

#include <boost/property_tree/ptree.hpp>
using boost::property_tree::ptree;

ptree pt;
ptree children;
ptree child1, child2, child3;

child1.put("", 1);
child2.put("", 2);
child3.put("", 3);

children.push_back(std::make_pair("", child1));
children.push_back(std::make_pair("", child2));
children.push_back(std::make_pair("", child3));

pt.add_child("MyArray", children);

write_json("test1.json", pt);

結果:

{
    "MyArray":
    [
        "1",
        "2",
        "3"
    ]
}

オブジェクト上の配列:

ptree pt;
ptree children;
ptree child1, child2, child3;


child1.put("childkeyA", 1);
child1.put("childkeyB", 2);

child2.put("childkeyA", 3);
child2.put("childkeyB", 4);

child3.put("childkeyA", 5);
child3.put("childkeyB", 6);

children.push_back(std::make_pair("", child1));
children.push_back(std::make_pair("", child2));
children.push_back(std::make_pair("", child3));

pt.put("testkey", "testvalue");
pt.add_child("MyArray", children);

write_json("test2.json", pt);

結果:

{
    "testkey": "testvalue",
    "MyArray":
    [
        {
            "childkeyA": "1",
            "childkeyB": "2"
        },
        {
            "childkeyA": "3",
            "childkeyB": "4"
        },
        {
            "childkeyA": "5",
            "childkeyB": "6"
        }
    ]
}

お役に立てれば

于 2012-10-10T14:19:34.663 に答える
22

あなたがする必要があるのは、この楽しみです。これは記憶によるものですが、このようなものは私にとってはうまくいきます。

boost::property_tree::ptree root;
boost::property_tree::ptree child1;
boost::property_tree::ptree child2;

// .. fill in children here with what you want
// ...

ptree.push_back( std::make_pair("", child1 ) );
ptree.push_back( std::make_pair("", child2 ) );

ただし、json の解析と書き込みにいくつかのバグがあることに注意してください。私がバグレポートを提出したもののいくつか - 応答なし:(

編集: {"":"","":""} として誤ってシリアル化することに関する懸念に対処する

これは、配列がルート要素である場合にのみ発生します。ブースト ptree ライターは、すべてのルート要素をオブジェクトとして扱います。配列や値ではありません。これは、boost/propert_tree/detail/json_parser_writer.hpp の次の行が原因です。

else if (indent > 0 && pt.count(Str()) == pt.size())

「インデント > 0 &&」を取り除くと、配列を正しく書き込むことができます。

生成されるスペースの量が気に入らない場合は、ここで提供したパッチを使用できます

于 2010-01-22T02:29:18.770 に答える
12

プロパティ ツリーを使用して JSON 構造を表現し始めたときに、同様の問題が発生しましたが、解決できませんでした。ドキュメントから、プロパティ ツリーは型情報を完全にはサポートしていないことにも注意してください。

JSON 値は、値を含むノードにマップされます。ただし、型情報はすべて失われます。数値、およびリテラル "null"、"true"、"false" は、文字列形式に単純にマップされます。

これを学んだ後、より完全な JSON 実装JSON Spiritに切り替えました。このライブラリは、JSON 文法の実装に Boost Spirit を使用し、配列を含む JSON を完全にサポートします。

別の C++ JSON 実装を使用することをお勧めします。

于 2010-01-22T09:21:52.650 に答える
6

私の場合、多かれ少なかれ任意の場所に配列を追加したかったので、マイケルの答えのように、子ツリーを作成し、配列要素を入力します。

using boost::property_tree::ptree;

ptree targetTree;
ptree arrayChild;
ptree arrayElement;

//add array elements as desired, loop, whatever, for example
for(int i = 0; i < 3; i++)
{
  arrayElement.put_value(i);
  arrayChild.push_back(std::make_pair("",arrayElement))
}

子が設定されたら、次のようにput_child()oradd_child()関数を使用して、子ツリー全体をターゲット ツリーに追加します...

targetTree.put_child(ptree::path_type("target.path.to.array"),arrayChild)

put_child 関数は引数にパスとツリーを取り、arrayChild を targetTree に「移植」します

于 2012-04-11T23:56:45.040 に答える
0

公式文書と上記の回答と混同しています。以下は私が理解していることです。

プロパティ ツリーはノードで構成されます。
各ノードは以下のようなものです

 struct ptree
    {
       map<key_name,value>          data;
       vector<pair<key_name,ptree>> children; 
    };

'put' で 'value' をデータに入れるに
は 'push_back' で 'node' を子に入れるには\

// Write 
    bt::ptree root;
    bt::ptree active;
    bt::ptree requested;
    bt::ptree n1, n2, n3;
        
    n1.put("name", "Mark");
    n1.put("age", 20);
    n1.put("job", "aaa");

    n2.put("name", "Rosie");
    n2.put("age", "19");
    n2.put("job", "bbb");

    n3.put("name", "sunwoo");
    n3.put("age", "10");
    n3.put("job", "ccc");

    active.push_back   ({ "",l1 });
    active.push_back   ({ "",l2 });
    requested.push_back({ "",l3 }); 
    root.push_back     ({"active", active});
    root.push_back     ({"requested", requested});

    bt::write_json("E:\\1.json", root);


    // READ
    bt::ptree root2;
    bt::ptree active2;
    bt::ptree requested2;
    bt::ptree r1, r2, r3;

    bt::read_json("E:\\1.json", root2);

    // loop children
    for (auto& [k,n] : root.get_child("active"))
    {       
        cout << n.get<string>("name", "unknown");
        cout << n.get<int>   ("age" , 11);
        cout << n.get<string>("job" , "man");
        cout << endl << flush;
    }
于 2021-06-30T11:08:47.247 に答える