Как сериализовать древовидную структуру в C++?

Я пытаюсь сериализовать / десериализовать игровую сцену для сетевой отправки/получения и сохранения/загрузки с / на диск.

мой игровой движок использует узлы и компоненты, и как таковые это единственные объекты, которые нуждаются в сериализации. Сцена может выглядеть так:

Root Node
  - Node
    - SpecializedComponent
    - SpecializedComponent
    - Node 
      - Node
  - Node
    - Node
    - Node
      - Node
        - Node
          - SpecializedComponent
  - Node

узел в основном это:

class Node {
    map<String, Node> mChildren;
    map<String, Component> mComponents;
    uuid_t mId;
    Node* mParent;
};

SpecializedComponent в основном это:

class SpecializedComponent : public Component {
    uuid_t mId;
    Node* mNode;
};

Я хотел бы использовать YAML или JSON для моего текстового представления этого. Я имейте Qt, Boost и любую другую библиотеку, которую я хотел бы иметь в своем распоряжении, поэтому зависимости не являются проблемой. Фактически, узлы уже являются Q_OBJECTS, поэтому у меня есть отражение.

несмотря на отражение, десериализация этого правильно обратно в древовидную структуру c++ кажется проблемой.

оптимально, я хотел бы элегантное и эффективное решение для сериализации / десериализации такой структуры в двоичный или текстовый формат.

4 ответов


спуск рекурсивный парсер обычно это более простой и достаточно мощный вариант для обработки части реконструкции. Я мог бы попытаться настроить какой-то код, чтобы показать в бетоне, в псевдокоде что-то вроде этого:

 Node *parse(stream s) {
  content = new Node;
  s >> content >> nsons;
  for (int c = 0; c < nsons; ++c)
   content->addChild(parse(s));
  return content; 
 }

конечно, когда компонент читается, мы должны проверить тип.


Я предлагаю вам, используя библиотека буферов протокола для этого. Поскольку вы сериализуете данные C++ для отправки по сети, вы будете очень полезны для того, что может предложить эта библиотека.


сериализация атрибутов узла Сериализуйте компоненты для этого узла. IE сериализует количество компонентов childs, затем каждый компонент.

чтобы сериализовать компонент, вы должны приписать идентификатор (int или строку) каждому типу компонента ( чтобы вы могли определить, как десериализовать определенный компонент относительно типа hs ) Сериализовать число дочерних узлов Сериализовать дочерние узлы (вызвать ту же функцию рекурсивно)

затем deserialisation является точной мирор. Unserialize, атрибуты узла, затем количество компонентов. Для каждого компонента получите тип компонента, десериализуйте его в соответствии с этим типом) и так далее...

Если вы используете Qt, qtextstream / QDataStream-самые простые варианты. Двоичный формат должен быть хорошо известен во время десериализации, поэтому вы должны поместить номер версии или идентификатор в начале вашего сериализованного контента, чтобы вы могли добавлять или изменять вещи позже.

кроме того, если вы должны быть совместимы с другими языками (как java) имейте в виду, что Qt не использует те же нормы для типов, что и string


Я думаю, вы можете сделать это с помощью Буст Сериализация. Он поддерживает сериализацию всех контейнеров STL, включая std::map.