Creating JSON arrays in Boost using Property Trees

匿名 (未验证) 提交于 2019-12-03 01:54:01

问题:

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



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!