首页 > 解决方案 > 向量反序列化的 YAML BadConversion 异常

问题描述

我正在使用 YAML 序列化我正在做的节点编辑器。在 YAML 文件中,我使用 YAML 映射和序列来存储根节点所具有的引脚信息,从而在 YAML 文件中形成下一个结构:

MainRootNode:
        ID: 1395587317
        Name: Main Node
        Type: 1
        InputPins:
          - Pin: 1352419211
            Name: Vertex Position (Vec3)
            DataType: 4
            Value: vec4(0.000000, 0.000000, 0.000000, 0.000000)
            AllowsMultipleTypes: false
            DefValue: vec4(0.000000, 0.000000, 0.000000, 0.000000)
          - Pin: 1289745580
            Name: Vertex Normal (Vec3)
            DataType: 4
            Value: vec4(0.000000, 0.000000, 0.000000, 0.000000)
            AllowsMultipleTypes: false
            DefValue: vec4(0.000000, 0.000000, 0.000000, 0.000000)
            //... And so on

当我尝试反序列化 vec4 值时,问题出现了,YAML 引发了 BadConversion 异常。这些值按如下方式序列化(在 YAML 命名空间内):

// --- Header dec ---
template<>
struct convert<glm::vec4>{ static Node encode(const glm::vec4& vec); };

// --- Cpp def ---
Node convert<glm::vec4>::encode(const glm::vec4& vec)
{
    Node node;
    node.push_back(vec.x);
    node.push_back(vec.y);
    node.push_back(vec.z);
    node.push_back(vec.w);
    node.SetStyle(EmitterStyle::Flow);
    return node;
}

然后,为了反序列化它们,我创建了下一个函数:

// --- Header dec ---
template<>
struct convert<glm::vec4>{ static bool decode(const Node& node, glm::vec4& vec); };

// --- Cpp def ---
bool convert<glm::vec4>::decode(const Node& node, glm::vec4& vec)
{
    if (!node.IsSequence() || node.size() != 4)
        return false;

    vec.x = node[0].as<float>();
    vec.y = node[1].as<float>();
    vec.z = node[2].as<float>();
    vec.w = node[3].as<float>();
    return true;
}

而且,调试时,我意识到该函数返回false,因为该节点不是序列并且它的大小为0。我一直在寻找这个问题的根源,但我无法找到它,是否有人看到错误?

将向量输入到 YAML Emitter 的代码如下:

YAML::Emitter& operator<<(YAML::Emitter& output, const glm::vec4& vec)
{
    output << YAML::Flow;
    output << YAML::BeginSeq << vec.x << vec.y << vec.z << vec.w << YAML::EndSeq;
    return output;
}

另外,我正在使用这种策略来反序列化场景对象,它工作正常,但不同之处在于,出于某种原因,它将 vecs 存储为[x, y, z]而不是vec3(x, y, z)(如在节点文件中),我不知道是否有某些东西与我遇到的问题有关。

标签: c++yaml

解决方案


从这个意义上说,您的 yaml 文件无效。如果您想像这样使用该值:

Value: vec4(0.000000, 0.000000, 0.000000, 0.000000)

然后您需要首先将节点作为字符串

Node["value"].as<std::string>();

然后,您需要使用子字符串编写自己的解析器并将值的字符串转换为浮点数。

或者,您可以使用有效的 yaml 作为值,我认为这可以为您节省大量工作和痛苦。一个例子:

Value:
    - 0.000000
    - 0.000000
    - 0.000000
    - 0.000000

然后解析它可能是这样的:

Node["Value"].as<std::vector<float>>();

然后你可以像对值一样使用数组。


推荐阅读