如何使用yaml-cpp发出复杂的数据结构?

时间:2011-09-02 16:33:19

标签: yaml-cpp

此问题的主要针对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的建议是:

  1. 使用我自己的数据结构将YAML存储在内存中,然后在序列化时以某种方式将其反馈给yaml-cpp(这实际上归结为重新实现YAML :: Node中的多态性,并且没有太大的不同从重新实现yaml-cpp的大部分,或

  2. “目前最好的方法是使用发射器并从节点的子节点中进行选择”,即文档中给出的示例。该方法的问题在于它仅适用于最简单的情况。假设我想在一系列地图中添加一个元素,其中地图的一个元素本身就是一个列表?这很快就会变得任意复杂!找到插入新数据的位置,发出操纵器,这一切都必须“手动”完成。

  3. 为了解决这个问题,Emitter是一个格式化程序,它的唯一输出是一个字符串,所以我唯一的选择就是用我的修改发出整个YAML文档,然后重新将它重新解析为一个新的内存中表示。如果我对文档进行了很多更改,那么此操作的效率足迹会很快增加。

    据我所知,修改现有节点存在实施挑战(您如何处理现有的节点数据或子节点数据?)。但是,在我看来,允许即时创建新的独立节点并插入到内存中的树应该至少是直截了当的。例如,这是如何实现JsonCpp的: http://jsoncpp.sourceforge.net

    如果效率低下,这至少会使您记录的“发射器”方法成为可行的可行方法。

    我很感激您对这些问题的看法。不幸的是,这些限制非常严重,并且考虑到yaml-cpp是唯一的C ++ / OO YAML库,我想知道除了切换到JSON之外是否还有一个实用的替代方案。

    非常感谢你的想法!

1 个答案:

答案 0 :(得分:1)

  

但是,在我看来,允许即时创建新的独立节点并插入到内存中的树应该至少是直截了当的。

我想这样做(我在这里看过JsonCpp),但有三个问题:

  1. YAML和JSON之间存在差异:YAML区分空节点和不存在的节点。

  2. yaml-cpp的当前行为是在请求不存在的节点时抛出异常。

  3. 在YAML中,映射可以有任意键。

  4. 对于问题#2,这意味着我们可能必须(主要是!)打破当前的行为,这让我犹豫不决。

    例如,在JsonCpp中,当你写

     root["encoding"];
    

    如果它不存在,它将为您创建一个默认节点。在yaml-cpp中,如果它不存在,它将抛出异常。人们可能依赖于以下代码:

    try {
      root["encoding"]; // etc
    catch(const YAML::Exception&) {
      // does not exist
    }
    

    最后,对于问题#3,您如何指定一个映射关键字?如果有人写了

    root[1] = 5;
    

    会将root实例化为具有null第一个元素的序列,还是具有单个键/值对{1, 5}的映射?如果是后者(这似乎更自然),那么

    root[0] = 3;
    root[1] = 5;
    

    root[1] = 5;
    root[0] = 3;
    

    会有不同的行为,这会违反直觉。

    基本上,最重要的是我已经考虑过这个问题,但是我还没有能够为它提供足够好的API。我很乐意这样做,所以如果你有任何想法,请告诉我。

    那就是说,我不确定stackoverflow是否是这样讨论的最佳位置(我在yaml-cpp网站上写过,因为很多人都在wiki上发布了如何提问) - 所以请随意给我发一封电子邮件(它在我的用户页面上)。