Ich möchte Enum/Bit Flags von Json setzen. Ich habe es geschafft, mein Objekt mit einem HashSet
mit meinen Enum-Werten zu serialisieren. Standardmäßig serialisiert LibGDX dies, fügt jedoch dem json ein Klassenfeld mit dem Typ des Satzes hinzu, damit es weiß, was zu tun ist. Ich möchte, dass meine Json sauber und von Java entkoppelt sein, damit ich diese Klasse schrieb:Deserialisieren von Enums als Flags verwenden
public class CriteriaSerializer implements Json.Serializer<HashSet> {
@Override
public void write(Json json, HashSet object, Class knownType) {
json.writeArrayStart();
for (Object o : object)
{
if (o instanceof Modifier.Criteria) {
json.writeValue(o, Modifier.Criteria.class);
}
}
json.writeArrayEnd();
}
@Override
public HashSet read(Json json, JsonValue jsonData, Class type) {
System.out.println("Running!?");
HashSet<Modifier.Criteria> criteriaSet = new HashSet<Modifier.Criteria>();
for (JsonValue entry = jsonData.child; entry != null; entry = entry.next)
{
criteriaSet.add(Modifier.Criteria.valueOf("ADD"));//Modifier.Criteria.valueOf(entry.asString()));
}
return criteriaSet;
}
}
Die Schreibmethode ergibt die folgende Ausgabe:
modifier: {
amount: 1 //Other field
criteriaSet: [
RED
BLUE
]
Alles was ich brauche ist es, diese Werte als Zeichenfolgen zu erhalten so kann ich etwas in Richtung myCriteriaSet.put(Criteria.valueOf(output)
tun. Die Sache ist, das Programm stürzt ab, bevor die Lese-Methode läuft. Ich vermute, das liegt daran, dass in den JSON-Daten ein ArrayList
gefunden wird, aber das entsprechende Feld im Objekt ist ein HashSet
. Dies ist der Fehler java.lang.IllegalArgumentException: Can not set java.util.Set field com.buckriderstudio.towercrawler.Creature.Modifier.criteriaSet to java.util.ArrayList
Sowohl schreiben und lesen von JSON ist mir wichtig, also brauche ich sie, um miteinander zu arbeiten. Am Ende bin ich nur auf der Suche nach einer sauberen Lösung, um EnumSet
oder Bitkombinationen lesbar zu (de) serialisieren. Ich fühle, dass ich in der Nähe bin, aber es könnte eine bessere Technik geben als die, die ich versuche.
Was ich an der LibgDX Json-Implementierung gefällt, ist, dass Felder nicht obligatorisch sind und Standardwerte haben können. Dies räumt die JSON-Daten erheblich auf, da ich viele Felder habe, die optional eingestellt werden können. Deshalb hat diese Bibliothek meine Vorliebe, Jackson zu sagen, aber ich habe nicht so viel mit Jackson gespielt.
EDIT
Dies ist eine Bearbeitung vor allem für Andreas. Soweit ich weiß (aber ich könnte falsch liegen), hat das nichts mit dem eigentlichen Problem zu tun. Andreas erklärt mir, dass die Json-Syntax falsch ist, Tatsache ist, dass es nicht einmal meine read
-Methode erreicht und dass die JSON-Bibliothek, die mit LibGDX ausgeliefert wird, nicht 100% korrektes Json schreibt. Muss es? Vielleicht um den Namen Json zu tragen? Muss es funktionieren? Ich denke nicht.
Hier ist mein Test. Alles, was ich mache, ist dieses Creature
Objekt zu erstellen und es mit 1 Codezeile zu analysieren. Es gibt keinen persönlichen Code von mir, der dies analysiert.
Creature c = new Creature("MadMenyo");
System.out.println(json.prettyPrint(c));
//Output
{
name: MadMenyo
modifier: {
amount: 1
criteriaSet: {
class: java.util.HashSet
items: [
VS_NATURE
MULTIPLY
]
}
}
stats: {
ENDURANCE: {
abbreviation: END
displayName: Endurance
baseValue: 8
finalValue: 8
}
MAGIC: {
abbreviation: MP
displayName: Your mana
baseValue: 20
finalValue: 20
}
STRENGTH: {
baseValue: 6
finalValue: 6
}
HEALTH: {
abbreviation: HP
displayName: Your life
baseValue: 100
finalValue: 100
}
}
}
//Looks like no valid Json to me. But the following line parses that correctly into a Creature object.
Creature jsonCreature = json.fromJson(Creature.class, jsonCreature);
Bevor wir noch weiter driften. Der Grund, warum ich das nicht verwenden möchte, ist, weil es die Klasse class: java.util.HashSet
ausgibt, und ich bin ziemlich sicher, dass das unnötig ist.
EDIT
Nachdem Sie die folgenden Zeilen von Code hinzufügen konnte ich richtig json ausgegeben wird. Trotzdem bricht der Code immer noch ab, bevor es zu meiner benutzerdefinierten Lese-Methode kommt. Die Frage bleibt, wie man entweder ein Enumset oder ein anderes, das Enums auf eine andere Weise hält, repariert oder serialisiert, solange es in Json lesbar ist und als Flags verwendet werden kann.
JsonWriter jw = new JsonWriter(new StringWriter());
json.setOutputType(JsonWriter.OutputType.json);
json.setWriter(jw);
//Now outputs proper Json
{
"name": "MadMenyo",
"modifier": {
"amount": 1,
"criteriaSet": [
"VS_NATURE",
"MULTIPLY"
]
},
"stats": {
"ENDURANCE": {
"abbreviation": "END",
"displayName": "Endurance",
"baseValue": 8,
"finalValue": 8
},
"MAGIC": {
"abbreviation": "MP",
"displayName": "Your mana",
"baseValue": 20,
"finalValue": 20
},
"STRENGTH": {
"baseValue": 6,
"finalValue": 6
},
"HEALTH": {
"abbreviation": "HP",
"displayName": "Your life",
"baseValue": 100,
"finalValue": 100
}
}
Das ist nicht gültig [JSON] (http://www.json.org/). Es fehlen 2 Kommas und die Array-Werte müssen in Anführungszeichen gesetzt werden. Bevor Sie weitermachen, stellen Sie sicher, dass Sie das Ergebnis verstehen, das Sie versuchen zu bekommen. – Andreas
@Andreas Es ist was meine Schreibmethode ausgibt. Kann wirklich Kommas nicht beeinflussen und zitiert afaik. – Madmenyo
Sie haben die write-Methode geschrieben, wenn Sie also das falsche Ergebnis erhalten, ist es Ihre Aufgabe, das Problem zu beheben. Sie sollten versuchen, Ihre Ausgabe zu testen, z. auf http://jsonlint.com/. Wenn es scheitert, machst du es falsch. Versuchen Sie nicht einmal, die 'read'-Methode zu testen, bis Sie ein gültiges JSON erhalten haben, was bedeutet, dass Ihre' write' Methode zuerst korrigiert werden muss. – Andreas