可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to create a JSON array using boost property trees.
The documentation says: "JSON arrays are mapped to nodes. Each element is a child node with an empty name."
So I'd like to create a property tree with empty names, then call write_json(...)
to get the array out. However, the documentation doesn't tell me how to create unnamed child nodes. I tried ptree.add_child("", value)
, but this yields:
Assertion `!p.empty() && "Empty path not allowed for put_child."' failed
The documentation doesn't seem to address this point, at least not in any way I can figure out. Can anyone help?
回答1:
Simple Array:
#include 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);
results in:
{ "MyArray": [ "1", "2", "3" ] }
Array over Objects:
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);
results in:
{ "testkey": "testvalue", "MyArray": [ { "childkeyA": "1", "childkeyB": "2" }, { "childkeyA": "3", "childkeyB": "4" }, { "childkeyA": "5", "childkeyB": "6" } ] }
hope this helps
回答2:
What you need to do is this piece of fun. This is from memory, but something like this works for me.
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 ) );
But watch out there's several bugs in the json parsing and writing. Several of which I've submitted bug reports for - with no response :(
EDIT: to address concern about it serializing incorrectly as {"":"","":""}
This only happens when the array is the root element. The boost ptree writer treats all root elements as objects - never arrays or values. This is caused by the following line in boost/propert_tree/detail/json_parser_writer.hpp
else if (indent > 0 && pt.count(Str()) == pt.size())
Getting rid of the "indent > 0 &&" will allow it to write arrays correctly.
If you don't like how much space is produced you can use the patch I've provided here
回答3:
When starting to use Property Tree to represent a JSON structure I encountered similar problems which I did not resolve. Also note that from the documentation, the property tree does not fully support type information:
JSON values are mapped to nodes containing the value. However, all type information is lost; numbers, as well as the literals "null", "true" and "false" are simply mapped to their string form.
After learning this, I switched to the more complete JSON implementation JSON Spirit. This library uses Boost Spirit for the JSON grammar implementation and fully supports JSON including arrays.
I suggest you use an alternative C++ JSON implementation.
回答4:
In my case I wanted to add an array to a more or less arbitrary location, so, like Michael's answer, create a child tree and populate it with array elements:
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
When the child has been populated, use the put_child()
or add_child()
function to add the entire child tree to the target tree, like this...
targetTree.put_child(ptree::path_type("target.path.to.array"),arrayChild)
the put_child function takes a path and a tree for an argument and will "graft" arrayChild into targetTree