2016-12-01 80 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了蝙蝠的權利。

如果有人知道如何在最初的問題中反序列化我的寫入方法,我將很樂意接受這個答案。