- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个程序可以在必要时修改 JSON 文档。该程序必须将一个 child 添加到另一个值,无论它是否已经是一个对象。该程序的行为应如下所示:
我看到了测试属性树值是否存在或它们是否为指定类型的方法,但没有测试它是否是对象的方法。
这是我制作的一个简单程序来说明我的意思:
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <sstream>
#include <iostream>
const char *json = "{"
"\"object\" : { \"mighty\" : \"wind\" },"
"\"boolean\" : true"
"}";
void printTree( std::string name, boost::property_tree::ptree tree )
{
std::cout << "Pass '" << name << "'" << std::endl;
try
{
std::stringstream ss;
boost::property_tree::write_json( ss, tree );
std::cout << ss.str() << std::endl;
}
catch( std::exception &e )
{
std::cout << "Could not make create json: " << e.what() << std::endl;
}
}
int main( int argc, char *argv[] )
{
boost::property_tree::ptree tree;
// Load it
std::istringstream ss_json( json );
boost::property_tree::read_json( ss_json, tree );
// Add a value to an object that doesn't exist
tree.put( "none.value", "hello!" );
// Print to see
printTree( "Nonexistent value test", tree );
// Add a value to the object
tree.put( "object.value", "bello!" );
// Print this one
printTree( "Adding value test", tree );
// Convert boolean to an object and add a value
tree.put( "boolean.value", "mello!" );
// Print it
printTree( "Converting value test", tree );
}
输出将是:
Pass 'Nonexistent value test'
{
"object": {
"mighty": "wind"
},
"boolean": "true",
"none": {
"value": "hello!"
}
}
Pass 'Adding value test'
{
"object": {
"mighty": "wind",
"value": "bello!"
},
"boolean": "true",
"none": {
"value": "hello!"
}
}
Pass 'Converting value test'
Could not make create json: <unspecified file>: ptree contains data that cannot be represented in JSON format
你可以在输出中看到,最后一步无法转换为 JSON(当我尝试设置它时没有抛出)。
如何实现上面列表中的场景 3?
最佳答案
If the key "x" exists and is ANY OTHER type, delete it, create an object with the key "x" and then add value y as a child. Also, they don't observe any of the JSON data types.
你的计划注定要失败。 Property Tree 不是 JSON 库。属性树可以在同一个节点上有数据和子节点。例如
ptree p;
auto& x = p.put_child("x", {});
x.put_value("hello");
write_json(std::cout, p);
打印
{
"x": "hello"
}
但是添加
/*auto& a = */ p.put_child("x.a", {});
write_json(std::cout, p);
terminate called after throwing an instance of 'boost::wrapexcept<boost::property_tree::json_parser::json_parser_error>'
what(): <unspecified file>: ptree contains data that cannot be represented in JSON format
解决方法是在添加属性之前或添加属性时删除任何值:
x.put_value("");
auto& a = p.put_child("x.a", {});
a.add("prop1", 123);
a.add("prop2", "one two three");
a.add("b.prop1", "nesting");
write_json(std::cout, p);
将打印 Live On Coliru
在清除值之前检查值的存在似乎更有效:
if (x.get_value_optional<std::string>()) {
x.put_value("");
}
但是由于 Property Tree 存储的字符串类型性质,没有区别,因为条件对于 std::string
始终为真。 (同样无法通过引用检索值。)
另请注意,在设置 n.prop1
嵌套属性时,如果您不控制源数据,则可能还必须检查 b
是否没有值,因为否则它会 fail again .
假设您的对象图结构是可以合理预测的(甚至是静态的),我建议您提前完成它:
for (auto key : { "x", "x.a", "x.a.b" }) {
if (auto child = p.get_child_optional(key)) {
std::cout << "clearing " << key << std::endl;
child->put_value("");
}
}
可以用一个助手来泛化:
clear_values("x.a.b", p);
可以实现为
void clear_values(ptree::path_type path, ptree& p) {
if (path.empty())
return;
auto head = path.reduce();
auto child = p.get_child_optional(head);
if (child) {
child->put_value("");
clear_values(path, *child);
}
}
事实上,有了这样的助手,还可以随时创建预期的层次结构:
void clear_values(ptree::path_type path, ptree& p, bool create = false) {
if (path.empty())
return;
auto head = path.reduce();
auto child = p.get_child_optional(head);
if (!child && create) {
child = p.put_child(head, {});
}
if (child) {
child->put_value("");
clear_values(path, *child, create);
}
}
现在它甚至可以在没有任何预先存在的数据的情况下运行良好:
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
using boost::property_tree::ptree;
void clear_values(ptree::path_type path, ptree& p, bool create = false) {
if (path.empty())
return;
auto head = path.reduce();
auto child = p.get_child_optional(head);
if (!child && create) {
child = p.put_child(head, {});
}
if (child) {
child->put_value("");
clear_values(path, *child, create);
}
}
int main() {
ptree p;
clear_values("x.a.b", p, true);
auto& a = p.get_child("x.a");
a.add("prop1", 123);
a.add("prop2", "one two three");
a.add("b.prop1", "nesting");
write_json(std::cout, p);
}
打印
{
"x": {
"a": {
"b": {
"prop1": "nesting"
},
"prop1": "123",
"prop2": "one two three"
}
}
}
关于c++ - 如何将任何值转换为对象并使用 boost::property_tree json 添加成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57727264/
我需要在我的程序中使用 boost::property_tree。现在我很难弄清楚如何将它与自定义路径类型一起使用。我想要的路径类型是 Framework::CommonClientServer::I
如何在循环数组时向属性树添加节点? 这可能是一件简单的事情,但我只是不明白如何使用 boost_property_tree。 我有一组值,我想将其添加到属性树并将其输出为 xml。如果我对节点进行硬编
请考虑两个“boost::property_tree”-s。 ptree1: { "node1" : 1, "node_that_only_appears_in_this_one" :
我正在使用 boost::property_tree 从/向文件加载/保存一组参数。其中许多参数是枚举(不同类型)。所以我需要一种从 boost::property_tree 获取枚举的方法(即将字符
我想使用 boost property_tree 解析下面的 xml 结构。 我能够解析上面 xml 的第一
是否可以在 boost 属性树中存储指向对象的指针,然后使用迭代器检索数据?我正在尝试做类似的事情: property_tree::ptree pt; pt.put("1.2.3.4", new My
感谢 Boost::Property_Tree,我正在尝试配置我的 XML 文件。我想要的聊天是: 10 我所拥有的是: first>10 我发现我不得不使用 boost::property_
我需要从文件中读取属性以影响程序行为。看起来 boost::property_tree 会做得很好。但是,我想知道在获取不同类型的值时,库是否可能会多次读取文件? 出于性能原因,我希望它只有一次。大多
我正在加载一个带有 boost property_tree 的 ini 文件。我的 ini 文件主要包含“简单”类型(即字符串、整数、 double 等),但我确实有一些值表示数组。 [Example
我的 JSON 是这样的: { "apps":[ { "id":"x", "val":"y", } ]
我发现 boost::property_tree::ptree 有巨大的内存开销。我的估计是一个空的 ptree 大约有 150 个字节,并且,放入 ptree 中的任何条目至少增加了 150 个字节
我想要的是这样的: Mr. Heik 37/100
我正在读取 xml 文件并存储到 boost::property_tree::ptree pt(object) 中。 我正在尝试使用在 ptree_serialization.hpp 中定义的方法 s
考虑以下示例: #include #include typedef boost::property_tree::ptree PT; struct Foo { int bar; in
假设我有两个 XML: foo foo 有没有办法在不指定绝对路径的情况下使用属性树从两个 xml 中提取 my_value? 目前我能做的最好的是: std::string first("some.
我正在类成员函数中执行 ptree.put()。 class Writer{ private: boost::property_tree::ptree ptree_; public:
我正在尝试使用显示的方法从 boost::property_tree 中读取数组数据 in this question .在该示例中,数组首先作为字符串读取,转换为字符串流,然后读入数组。在实现该解决
我正在寻找与 boost::property_tree 非常相似的结构.但是它应该更加类型安全,例如我想在我这样做时得到一个异常(exception): #include int main() {
我需要解析一些 INI 文件。为此,我尝试使用 boost::property_tree,但在我的系统中不允许出现异常。 如何在使用 boost::property_tree 时禁用异常支持? 如果没
如何从 boost::property_tree 中获取枚举? 这是我的“非工作”示例。 配置文件 EMISSION::EMIT1 42 main.cpp #include #inclu
我是一名优秀的程序员,十分优秀!