# Yaml File lesen und in Objekte umwandel (SnakeYAML / YamlBeans)



## JBoby (10. Aug 2015)

Servus Leute,

ich bin neu im Forum also wenn ich hier im falschen Thread gelandet bin oder wichtige Infos fehlen, dann weist mich einfach darauf hin. 

Hier schon mal ein paar Links zu den Librarys / Websites die ich verwendet habe:

snakeYAML: https://bitbucket.org/asomov/snakeyaml
YamlBeans: https://github.com/EsotericSoftware/yamlbeans
Allgemeine yaml Seite: http://yaml.org/

Also nun zu meinem Problem/Frage ich arbeite Momentan an einem Tool für ein Online-Spiel _(EvE-Online vielleicht erkennen manche dann schon meine Zielsetzung). _Bei dem Tool muss ich Dateien die vom Spielhersteller zu jedem Patch herausgegeben werden einlesen, diese Dateien sind .yaml Files und enthalten unter anderem Informationen über Items (z.B. ID's, Namen, Volumen etc.). Der Inhalt sieht ungefähr so aus: 









Jetzt wollte ich diese Dateien mithilfe der Library snakeyaml einlesen und zu Objekten umwandeln.
Dazu habe ich mir mal eine ganz einfache Klasse geschrieben:


```
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.error.YAMLException;


public class Yaml_Reader {
   
    public Yaml_Reader() throws IOException{
        try {
            this.loadYamlFile();
        } catch (YAMLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       
    }
   
    public void loadYamlFile() throws IOException{
       
       
        FileReader file = new FileReader("D:/Eigene Dateien/Downloads/Games/Eve-Online/Static Data/Aegis_1.2_114300_db/skinMaterials.yaml");   
        Yaml yaml = new Yaml();
   
        skinMaterials skinM =  yaml.loadAs(file, skinMaterials.class);
               
        System.out.println(skinM.getSkinMaterialID());
           
       
    }
   

    public static void main(String[] args) throws IOException {
        new Yaml_Reader();
    }

}
```

Die *skinMaterials*-Klasse habe ich noch als *Config* geschrieben, damit *snakeYAML *weiß, wie er den Inhalt der Datei umwandelt muss.


```
public class skinMaterials {

   
    private String colorHull;
    private String colorPrimary;
    private String colorSecondary;
    private String colorWindow;
    private int displayNameID;
    private String material;
    private int skinMaterialID;
   
   
    public String getColorHull() {
        return colorHull;
    }
    public void setColorHull(String colorHull) {
        this.colorHull = colorHull;
    }
    public String getColorPrimary() {
        return colorPrimary;
    }
    public void setColorPrimary(String colorPrimary) {
        this.colorPrimary = colorPrimary;
    }
    public String getColorSecondary() {
        return colorSecondary;
    }
    public void setColorSecondary(String colorSecondary) {
        this.colorSecondary = colorSecondary;
    }
    public String getColorWindow() {
        return colorWindow;
    }
    public void setColorWindow(String colorWindow) {
        this.colorWindow = colorWindow;
    }
    public int getDisplayNameID() {
        return displayNameID;
    }
    public void setDisplayNameID(int displayNameID) {
        this.displayNameID = displayNameID;
    }
    public String getMaterial() {
        return material;
    }
    public void setMaterial(String material) {
        this.material = material;
    }
    public int getSkinMaterialID() {
        return skinMaterialID;
    }
    public void setSkinMaterialID(int skinMaterialID) {
        this.skinMaterialID = skinMaterialID;
    }
   
   
   
}
```

Jetzt habe ich aber folgende _Fehlermeldung _bekommen:


```
Can't construct a java object for tag:yaml.org,2002:skinMaterials; exception=Class not found: skinMaterials
in "<reader>", line 1, column 1:
    1:
    ^

    at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.construct(Constructor.java:333)
    at org.yaml.snakeyaml.constructor.BaseConstructor.constructObject(BaseConstructor.java:183)
    at org.yaml.snakeyaml.constructor.BaseConstructor.constructDocument(BaseConstructor.java:142)
    at org.yaml.snakeyaml.constructor.BaseConstructor.getSingleData(BaseConstructor.java:128)
    at org.yaml.snakeyaml.Yaml.loadFromReader(Yaml.java:480)
    at org.yaml.snakeyaml.Yaml.loadAs(Yaml.java:440)
    at Yaml_Reader.loadYamlFile(Yaml_Reader.java:39)
    at Yaml_Reader.<init>(Yaml_Reader.java:20)
    at Yaml_Reader.main(Yaml_Reader.java:49)
Caused by: org.yaml.snakeyaml.error.YAMLException: Class not found: skinMaterials
    at org.yaml.snakeyaml.constructor.Constructor.getClassForNode(Constructor.java:634)
    at org.yaml.snakeyaml.constructor.Constructor$ConstructYamlObject.getConstructor(Constructor.java:321)
    at org.yaml.sn
```

So dumm gelaufen dachte ich mir, also hab ich einfach mal eine andere Library verwenden, nämlich YamlBeans und zwar mit folgendem Code:


```
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.esotericsoftware.yamlbeans.YamlException;
import com.esotericsoftware.yamlbeans.YamlReader;


public class Yaml_Reader {
   
   
   
   
   
    public Yaml_Reader() throws IOException{
        try {
            this.loadYamlFile();
        } catch (YamlException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       
    }
   
   
    public void loadYamlFile() throws IOException{
       
       
        FileReader file = new FileReader("D:/Eigene Dateien/Downloads/Games/Eve-Online/Static Data/Aegis_1.2_114300_db/skinMaterials.yaml");   
        YamlReader yaml = new YamlReader(file);
        skinMaterials  skinM = yaml.read(skinMaterials.class);
       
               
        System.out.println(skinM.getSkinMaterialID());
           
       
    }
   
   

    public static void main(String[] args) throws IOException {
        new Yaml_Reader();
    }

}
```


Und wer hätte es gedacht, wieder kam nur Mist raus:


```
com.esotericsoftware.yamlbeans.YamlReader$YamlReaderException: Line 0, column 2: Unable to find property '1' on class: skinMaterials
    at com.esotericsoftware.yamlbeans.YamlReader.readValueInternal(YamlReader.java:264)
    at com.esotericsoftware.yamlbeans.YamlReader.readValue(YamlReader.java:154)
    at com.esotericsoftware.yamlbeans.YamlReader.read(YamlReader.java:107)
    at com.esotericsoftware.yamlbeans.YamlReader.read(YamlReader.java:92)
    at Yaml_Reader.loadYamlFile(Yaml_Reader.java:34)
    at Yaml_Reader.<init>(Yaml_Reader.java:20)
    at Yaml_Reader.main(Yaml_Reader.java:45)
```

Aber diesmal wusste ich anhand der Fehlermeldung warum es nicht funktioniert hat, nämlich weil die "ID's" die immer am Anfang jedes "Objektes" stehen gar nicht in der Config stehen. Also hab ich zum Testen einfach mal eines davon rauskopiert:





Und siehe da, es kam diesmal tatsächlich eine 1 raus 

So jetzt habe ich also ne ganze Menge Probleme:

1. Mein Test bringt mich ja nun nicht unbedingt weiter, ich muss dem Parser in der config ja irgendwie beibringen, dass die "ID's" am Anfang (1,2,3,4...) auch teile der Objekte und nicht die Objekttypen sind.

2. Ich muss/will die Objekte in einer HashMap laden, sonst habe ich ja nicht allzu viel davon, momentan würde nur eines der Objekte (und zwar das zuletzt) geladene in der Variable skinM bestehen bleiben.

3. Weil das Laden noch nicht funktioniert kann ich folgenden "Sonderfall" nicht testen:




 In dieser Datei (die eigentlich wichtigste Datei) hat nicht jedes Objekt alle die gleichen Attributen bei manchen gibt es wie hier im Bild keine "soundID" oder eine "mass". Wie geht der Parser damit um wenn in der Config alle Attribute aufgeführt sind aber in der Datei manche davon fehlen?


Ich hoffe ihr könnt mir weiterhelfen denn ansonsten werde ich wohl gezwungen sein mir mit dem FileReader und massig if-Abfragen mit .equals was zurechtzubasteln und ich denke nicht dass das nötig ist, sondern das ich momentan nur zu blöd / unwissend bin um die Libraries richtig anzuwenden. 

Danke schonmal im Vorraus

JBoby


----------

