yamldeserializationabstract-class

Serializing and Deserializing abstract classes in YAML


Let's say we have a game, characters in which have special abilities. All abilities share an abstract base type called AbstractAbility. Each character has a list of said base type (List), elements of which are objects of derived classes (List example = new List(){new StompAbility(), new TeleportAbility()}).

The problem is that said list needs to be changeable throught a config file, but YAML cannot deserialize AbstractClasses properly.

As of now I can bypass this issue by adding a field to AbstcractAbility class called AbilityType which contains the name of the derived class it belongs to, basically telling YAML what type it is actually trying to deserialize. However is there a way I can achieve the desirable result without having to resort to such measures?


Solution

  • YAML supports tags which have been designed for this use-case:

    characters:
      - name: John
        abilities:
          - !StompAbility
            name: Stomp
            stompiness: 12
            abilityPoints: 2
          - !TeleportAbility
            name: Teleport
            range: 200m
            abilityPoints: 5
    

    By tagging the list entries, the code deserializing the YAML can then select the appropriate class for the entry.

    Support for tags varies between YAML implementations. Some (e.g. PyYAML, SnakeYaml) allow you to explicitly register tags and link them to types. Others (e.g. go-yaml, libyaml) only emit the tags and you need to process them yourself.