2016-12-01 30 views
0

我希望能够从Json中设置枚举/比特标志。我设法使用包含我的枚举值的HashSet序列化我的对象。默认情况下,LibGDX对此进行序列化,但将类型设置的类字段添加到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; 
    } 
} 

写方法产生以下的输出:

modifier: { 
    amount: 1 //Other field 
    criteriaSet: [ 
     RED 
     BLUE 
    ] 

所有我需要的是让这些值作为字符串所以我可以按照myCriteriaSet.put(Criteria.valueOf(output)的方法做一些事情。事情是,程序在读取方法运行之前崩溃。我想这是因为它在json数据中找到了ArrayList,但对象中的对应字段是HashSet。这是错误java.lang.IllegalArgumentException: Can not set java.util.Set field com.buckriderstudio.towercrawler.Creature.Modifier.criteriaSet to java.util.ArrayList

写入和从json读取对我很重要,所以我需要他们与彼此合作。最后,我只是寻找一个干净的解决方案来获取(德)以可读的方式序列化EnumSet或位组合。我觉得我很接近,但可能会有更好的技术,然后我正在尝试。

我对LibgDX Json实现的喜欢是,字段不是强制性的,可以有默认值。这会清理JSON数据,因为我有很多可以选择设置的字段。因此,这个图书馆有我喜欢说杰克逊,但我还没有玩过杰克逊那么多。

编辑

这是专为安德烈亚斯编辑。据我所知(但我可能是错的),这与实际问题无关。 Andreas向我解释Json的语法是错误的,事实是它甚至没有达到我的方法,并且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类,我很确定这是不必要的。

EDIT

添加以下代码行后我设法输出正确JSON。然而,代码在达到我自定义的读取方法之前仍然会中断。问题仍然是如何解决这个问题,或者只要它在Json中可读并且可以用作标志,就可以用不同的方式保存Enumset或其他持续枚举的序列化。

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

这是无效的[JSON](http://www.json.org/)。它缺少2个逗号,并且需要引用数组值。在继续之前,请确保你了解你试图获得的结果。 – Andreas

+0

@Andreas这是我写的方法输出。不能真正影响逗号并引用afaik。 – Madmenyo

+0

您编写了写入方法,因此如果它产生错误的结果,那么解决它是您的工作。您应该尝试测试您的输出,例如在http://jsonlint.com/。如果失败了,你做错了。在获得有效的JSON之前,不要尝试测试'read'方法,这意味着您的'write'方法必须先被修复。 – Andreas

回答

0

虽然这不完全回答我的问题,因为它仍然崩溃它到达读取方法前,我已经找到了合适的工作,周围用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了蝙蝠的权利。

如果有人知道如何在最初的问题中反序列化我的写入方法,我将很乐意接受这个答案。