我希望能够从Json设置枚举/位标志。我已设法使用包含我的枚举值的HashSet
来序列化我的对象。默认情况下,LibGDX对此进行序列化,但是将类型为set的类字段添加到json,以便它知道该怎么做。我希望我的json干净并与java分离,所以我写了这个类:
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;
}
}
write方法产生以下输出:
modifier: {
amount: 1 //Other field
criteriaSet: [
RED
BLUE
]
我所需要的只是将这些值作为字符串,以便我可以按照myCriteriaSet.put(Criteria.valueOf(output)
的方式执行某些操作。问题是,程序在read方法运行之前崩溃了。我想这是因为它在json数据中找到ArrayList
但对象中的相应字段是HashSet
。这是错误java.lang.IllegalArgumentException: Can not set java.util.Set field com.buckriderstudio.towercrawler.Creature.Modifier.criteriaSet to java.util.ArrayList
写作和阅读json对我来说都很重要,所以我需要他们互相合作。最后,我只是寻找一种干净的解决方案,以可读的方式获取(de)序列化EnumSet
或位组合。我觉得我很接近但是我可能会尝试一种更好的技术。
我喜欢LibgDX Json实现的是字段不是必需的,可以有默认值。这会大大清理json数据,因为我有很多可以选择设置的字段。因此,这个图书馆我更喜欢说杰克逊,但我还没有和杰克逊玩过那么多。
修改
这是特别为Andreas编辑的。据我所知(但我可能错了)这与实际问题无关。 Andreas向我解释说Json语法是错误的,事实是它甚至没有达到我的read
方法,并且LibGDX附带的json库没有写出100%正确的Json。它需要吗?也许以Json为名?它需要工作吗?我不这么认为。
这是我的测试。我所做的只是创建这个Creature
对象并用1行代码解析它。我没有涉及解析此问题的个人代码。
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);
在我们进一步离开之前。我之所以不想使用它,是因为它输出了类class: java.util.HashSet
,而且我非常确定这是不必要的。
修改
添加以下代码行后,我设法输出正确的json。然而代码在进入我的自定义读取方法之前仍然会中断。问题仍然是如何修复或以不同的方式序列化Enumset或其他Set
持有枚举,只要它在Json中是可读的并且可以用作标志。
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
}
}
答案 0 :(得分:1)
虽然这并没有完全回答我的问题,因为它在进入read方法之前仍然崩溃,我找到了一个合适的工作来使用Jackson
库。我已经想出如何通过在要序列化的类上使用以下注释来忽略默认值:@JsonInclude(JsonInclude.Include.NON_DEFAULT)
。这让我得到了正确的json输出,就像我在json序列化程序中使用构建一样。唯一的缺点是速度,杰克逊在一个物体上慢了大约20倍,但循环1000次使它“仅”慢了约5倍。
对于任何不知道的人,这就是你如何将杰克逊与LibGDX整合:
在build
中为核心项目添加依赖项。
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.0.1'
开始解析只需要几行。
ObjectMapper mapper = new ObjectMapper();
//Add pretty print indentation
mapper.enable(SerializationFeature.INDENT_OUTPUT);
//When serializing we have to wrap it in a try/catch signature
try {
mapper.writeValue(Gdx.files.local("creature.json").file(), creature);
} catch (IOException e) {
e.printStackTrace();
}
//To map it back to a object we do the same
Creature jsonCreature = null;
try {
jsonCreature = mapper.readValue(Gdx.files.local("creature.json").readString(), Creature.class);
} catch (IOException e) {
e.printStackTrace();
}
//Jackson also has control over what you want to serialize
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
//Or with annotation in front of the class
@JsonIgnoreProperties({"nameOfProperty", "anotherProperty"})
这至少给了我与json序列化程序中构建相同的能力,它立即将EnumSet
序列化。
如果有人知道如何在最初的问题中反序列化我的写法,我很乐意接受这个作为答案。