如何使用 yaml-cpp 发出复杂的数据结构?
Posted
技术标签:
【中文标题】如何使用 yaml-cpp 发出复杂的数据结构?【英文标题】:How to use yaml-cpp to emit a complicated data structure? 【发布时间】:2011-09-02 16:33:19 【问题描述】:此问题主要针对 yaml-cpp (Jesse Beder) 的作者,他要求在此处发布有关 yaml-cpp 使用的问题。
在许多位置,包括 yaml-cpp 文档, http://code.google.com/p/yaml-cpp/wiki/HowToEmitYAML#Using_Existing_Nodes
您提到 yaml-cpp 不提供修改内存中现有 YAML::Node 对象的方法,您对修改内存中 YAML 的建议是:
使用我自己的数据结构将 YAML 存储在内存中,然后在序列化时以某种方式将其反馈给 yaml-cpp(本质上归结为在 YAML::Node 中重新实现多态性,并没有太大区别从重新实现大部分 yaml-cpp),或
“目前最好的方法是使用发射器并从节点的子节点中挑选”,即文档中给出的示例。这种方法的问题在于它只适用于最简单的情况。假设我想向一系列地图添加一个元素,其中地图的一个元素本身就是一个列表?这会很快变得任意复杂!找到插入新数据的位置,发出操纵器,这一切都必须“手动”完成。
为了使问题更加复杂,Emitter 是一个格式化程序,它的唯一输出是一个字符串,所以我唯一的选择是发出带有我修改的整个 YAML 文档,然后重新将其重新解析为新的内存表示。如果我对文档进行大量更改,此操作的效率足迹会迅速增加。
我了解修改现有节点存在实施挑战(您如何处理对节点数据或子节点数据的现有引用?)。但是,在我看来,允许动态创建新的、独立的节点并将其插入内存树中至少应该是简单的。例如,JsonCpp 是如何实现的: http://jsoncpp.sourceforge.net
如果效率低下,这至少可以使您记录的“发射器”方法成为一种潜在可行的解决方法。
感谢您对这些问题的看法。不幸的是,这些限制非常严重,并且鉴于 yaml-cpp 是目前唯一的 C++/OO YAML 库,我想知道除了切换到 JSON 之外是否还有其他实用的替代方案。
非常感谢您的想法!
【问题讨论】:
【参考方案1】:但是,在我看来,允许动态创建新的、独立的节点并将其插入内存树中至少应该很简单。
我很想做这个(并且我在这里查看了 JsonCpp),但是存在三个问题:
YAML 和 JSON 有区别:YAML 区分空节点和不存在的节点。
yaml-cpp当前的行为是在请求不存在的节点时抛出异常。
在 YAML 中,映射可以有任意键。
对于问题 #2,这意味着我们可能必须(主要!)打破当前的行为,这让我犹豫不决。
例如在JsonCpp中,当你写
root["encoding"];
如果它不存在,它将为您创建一个默认节点。在 yaml-cpp 中,如果不存在就会抛出异常。人们可能依赖如下代码:
try
root["encoding"]; // etc
catch(const YAML::Exception&)
// does not exist
最后,对于问题 #3,您将如何指定作为映射的键?如果有人写了
root[1] = 5;
将root
实例化为具有空第一个元素的序列,还是具有单个键/值对1, 5
的映射?如果是后者(看起来更自然),那么
root[0] = 3;
root[1] = 5;
和
root[1] = 5;
root[0] = 3;
会有不同的行为,这是违反直觉的。
基本上,最重要的是我已经考虑过这个问题,但是我还没有为它想出一个足够好的 API。我很乐意这样做,所以如果您有任何想法,请告诉我。
也就是说,我不确定 *** 是否是进行此类讨论的最佳场所(我在 yaml-cpp 网站上写了这篇文章,因为很多人都在 wiki 上发布了操作方法问题) - 所以请随意给我发一封电子邮件(在我的用户页面上)。
【讨论】:
非常感谢您快速周到的回复,杰西。对此,我真的非常感激。我确实会发邮件给你跟进。以上是关于如何使用 yaml-cpp 发出复杂的数据结构?的主要内容,如果未能解决你的问题,请参考以下文章