Reputation: 315
I understand that boost::property_tree::ptree
may contain key-value pairs where the 'value' may be of any type. Now my question is that, now my 'value' is a std::map
, and when I attempt to pt.get<std::map<std::string, std::string>>
where pt
is a property tree, I get a compile time error. Hence, my question is:
How to extract a STL map value from a boost property tree? If this is not possible, is there any way of converting between STL map and boost property tree (so that each node of the property tree is not a STL container but a simple data type).
Upvotes: 3
Views: 1100
Reputation: 393799
Very simply:
ptree pt;
std::map<std::string, ptree> m(pt.begin(), pt.end());
However, note that keys need not be unique:
std::multimap<std::string, ptree> mm(pt.begin(), pt.end());
And if you are want to transform all values to std::string
(assuming they all have a string value):
std::map<std::string, std::string> dict;
for (auto& [k,v]: pt) {
dict.emplace(k, v.get_value<std::string>());
}
#include <boost/property_tree/ptree.hpp>
#include <map>
#include <fmt/ranges.h>
using boost::property_tree::ptree;
template<> struct fmt::formatter<ptree> : fmt::formatter<std::string>
{
template<typename Ctx>
auto format(ptree const& pt, Ctx& ctx) {
return format_to(ctx.out(), "'{}'", pt.get_value<std::string>());
}
};
int main() {
ptree pt;
pt.put("keyA", "valueA-1");
pt.put("keyB", "valueB");
pt.put("keyC", "valueC");
pt.add("keyA", "valueA-2"); // not replacing same key
std::map<std::string, ptree> m(pt.begin(), pt.end());
std::multimap<std::string, ptree> mm(pt.begin(), pt.end());
std::map<std::string, std::string> dict;
for (auto& [k,v]: pt) {
dict.emplace(k, v.get_value<std::string>());
}
fmt::print(
"map:\n\t{}\n"
"multimap:\n\t{}\n"
"dict:\n\t{}\n",
fmt::join(m, "\n\t"),
fmt::join(mm, "\n\t"),
fmt::join(dict, "\n\t")
);
}
Prints
map:
("keyA", 'valueA-1')
("keyB", 'valueB')
("keyC", 'valueC')
multimap:
("keyA", 'valueA-1')
("keyA", 'valueA-2')
("keyB", 'valueB')
("keyC", 'valueC')
dict:
("keyA", "valueA-1")
("keyB", "valueB")
("keyC", "valueC")
template <typename MapLike>
ptree ptree_from_map(MapLike const& m) {
ptree pt;
for (auto const& [k,v]: m) {
pt.add(k, v);
}
return pt;
}
Upvotes: 4