I want to be able to set enum/bit flags from Json. I have managed to serialize my object with a HashSet
containing my enum values. By default LibGDX serializes this but adds a class field with the type of set to the json so it knows what to do. I want my json to be clean and decoupled from java so I wrote this class:
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;
}
}
The write method results in the following output:
modifier: {
amount: 1 //Other field
criteriaSet: [
RED
BLUE
]
All I need is to get those values as strings so I can do something along the lines of myCriteriaSet.put(Criteria.valueOf(output)
. The thing is, the program crashes before the read method is running. I guess this is because it finds an ArrayList
in the json data but the corresponding field in the object is a HashSet
. This is the error java.lang.IllegalArgumentException: Can not set java.util.Set field com.buckriderstudio.towercrawler.Creature.Modifier.criteriaSet to java.util.ArrayList
Both writing to- and reading from json is important to me so I need them to work with eachother. In the end I'm just looking for a clean solution to get (de)serialize EnumSet
or bit combinations in a readable manner. I feel I'm close but there might be a better technique then the one I'm trying.
What I like about the LibgDX Json implementation is that fields are not mandatory and can have default values. This cleans up the json data considerably since I have a lot of fields that can be set optionally. Therefor this library has my preference to say Jackson, but I have not played around with Jackson all that much though.
EDIT
This is an edit especially for Andreas. As far as I know (but I might be wrong) this has nothing to do with the actual problem. Andreas is explaining to me that the Json syntax is wrong, the fact is that it does not even reach my read
method and that the json library that ships with LibGDX is not writing 100% correct Json. Does it need to? Perhaps to bear the name Json? Does it need to to work? I don't think so.
Here is my test. All I do is create this Creature
object and parse it with 1 line of code. There is no personal code of me involved in parsing this.
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);
Before we drift off even further. The reason why I do not want to use this is because it outputs the class class: java.util.HashSet
and I'm pretty sure that is unnecessary.
EDIT
After adding the following lines of code I managed to output correct json. Yet the code still breaks before it gets to my custom read method. The question remain how to either fix that or serialize a Enumset or other Set
holding enums in a different way as long as it is readable in Json and can be used as flags.
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
}
}