2017-02-03 87 views
0

我試圖爲使用JSON文件的遊戲創建緩存。編寫和檢索這些數據將通過使用GSON完成。我有一個包含多個對象的JSON文件,在這些對象中也存儲了其他對象。使用Gson從JSON文件檢索嵌套的對象

我的問題是:如何檢索這個數據的最佳方式?

對象1:

public class GameItem { 

    private final int id; 
    private final String name; 
    private final String description; 
    private final int shopValue; 
    private final ItemStats stats; 

    public GameItem(int id, String name, String description, int shopValue, ItemStats stats) { 
     this.id = id; 
     this.name = name; 
     this.description = description; 
     this.shopValue = shopValue; 
     this.stats = stats; 
    } 

    public int getId() { 
     return id; 
    } 

    public String getName() { 
     return name; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public int getShopValue() { 
     return shopValue; 
    } 

    public ItemStats getStats() { 
     return stats; 
    } 

} 

對象2:

public class ItemStats { 

    private final int stabAttack; 
    private final int slashAttack; 
    private final int crushAttack; 
    private final int magicAttack; 
    private final int rangeAttack; 
    private final int stabDefence; 
    private final int slashDefence; 
    private final int crushDefence; 
    private final int magicDefence; 
    private final int rangeDefence; 
    private final int strengthBonus; 
    private final int prayerBonus; 

    public ItemStats(int stabAttack, int slashAttack, int crushAttack, int magicAttack, int rangeAttack, int stabDefence, int slashDefence, int crushDefence, int magicDefence, int rangeDefence, int strengthBonus, int prayerBonus) { 
     this.stabAttack = stabAttack; 
     this.slashAttack = slashAttack; 
     this.crushAttack = crushAttack; 
     this.magicAttack = magicAttack; 
     this.rangeAttack = rangeAttack; 
     this.stabDefence = stabDefence; 
     this.slashDefence = slashDefence; 
     this.crushDefence = crushDefence; 
     this.magicDefence = magicDefence; 
     this.rangeDefence = rangeDefence; 
     this.strengthBonus = strengthBonus; 
     this.prayerBonus = prayerBonus; 
    } 

    public int getStabAttack() { 
     return stabAttack; 
    } 

    public int getSlashAttack() { 
     return slashAttack; 
    } 

    public int getCrushAttack() { 
     return crushAttack; 
    } 

    public int getMagicAttack() { 
     return magicAttack; 
    } 

    public int getRangeAttack() { 
     return rangeAttack; 
    } 

    public int getStabDefence() { 
     return stabDefence; 
    } 

    public int getSlashDefence() { 
     return slashDefence; 
    } 

    public int getCrushDefence() { 
     return crushDefence; 
    } 

    public int getMagicDefence() { 
     return magicDefence; 
    } 

    public int getRangeDefence() { 
     return rangeDefence; 
    } 

    public int getStrengthBonus() { 
     return strengthBonus; 
    } 

    public int getPrayerBonus() { 
     return prayerBonus; 
    } 
} 

JSON數據:

[ 
    { 
     "id": 0, 
     "name": "Dwarf_remains", 
     "description": "The_body_of_a_Dwarf_savaged_by_Goblins.", 
     "shopValue": 1, 
     "stats": [ 
      "stabAttack": 0, 
      "slashAttack": 0, 
      "crushAttack": 0, 
      "magicAttack": 0, 
      "rangeAttack": 0, 
      "stabDefence": 0, 
      "slashDefence": 0, 
      "crushDefence": 0, 
      "magicDefence": 0, 
      "rangeDefence": 0, 
      "strengthBonus": 0, 
      "prayerBonus": 0 
     ] 
    }, 
    { 
     "id": 1, 
     "name": "Toolkit", 
     "description": "Good_for_repairing_a_broken_cannon.", 
     "shopValue": 1, 
     "stats": [ 
      "stabAttack": 0, 
      "slashAttack": 0, 
      "crushAttack": 0, 
      "magicAttack": 0, 
      "rangeAttack": 0, 
      "stabDefence": 0, 
      "slashDefence": 0, 
      "crushDefence": 0, 
      "magicDefence": 0, 
      "rangeDefence": 0, 
      "strengthBonus": 0, 
      "prayerBonus": 0 
     ] 
    }, 
    { 
     "id": 2, 
     "name": "Cannonball", 
     "description": "Ammo_for_the_Dwarf_Cannon.", 
     "shopValue": 3000, 
     "stats": [ 
      "stabAttack": 0, 
      "slashAttack": 0, 
      "crushAttack": 0, 
      "magicAttack": 0, 
      "rangeAttack": 0, 
      "stabDefence": 0, 
      "slashDefence": 0, 
      "crushDefence": 0, 
      "magicDefence": 0, 
      "rangeDefence": 0, 
      "strengthBonus": 0, 
      "prayerBonus": 0 
     ] 
    } 
] 
+0

你做得很好,只是讓私人最終ItemStats統計私人最終名單統計,因爲它是一個數組的「統計」走出:[......],但你缺少[{} ... 。]在json中的數組內部,所以也許。 –

+0

不確定你的意思,請你舉個例子嗎? – Fryslan

回答

0

不能有任何 「最好」 的方式,因爲它可能取決於你的真實案件。但是爲了反序列化,並有效地序列回到這個對象,你必須:

  • 首先,解決您的JSON文件

因爲它的語法非法的:作爲一個對象包圍的stats屬性應申報與{}(不作爲與[陣列和]):

"stats": { 
    "stabAttack": 0, 
    "slashAttack": 0, 
    "crushAttack": 0, 
    "magicAttack": 0, 
    "rangeAttack": 0, 
    "stabDefence": 0, 
    "slashDefence": 0, 
    "crushDefence": 0, 
    "magicDefence": 0, 
    "rangeDefence": 0, 
    "strengthBonus": 0, 
    "prayerBonus": 0 
} 
  • 使用給GSON真實類型的數組元素的適當TypeToken

這是一個特殊GSON機構指定目標類型(各種庫使用類似技術)。指定List.class作爲源的類型將不起作用,實質上導致List<Map<String, Object>>由於Java泛型工作(類型參數化只能寫入類,字段或方法,但不直接寫入實例,除非它們本身具有足夠的類型信息或者使用自定義的反序列化器,這些反序列化器知道可以從哪裏獲得這些信息[比如說一個特殊的合成領域])。

private static final TypeToken<List<GameItem>> listOfGamesTypeToken = new TypeToken<List<GameItem>>() { 
}; 

注意,類型令牌是線程安全(以及Gson實例是),並可以在全球容易共享(但明智地)。

  • 適用緩衝讀出,和我寫/ O流

的最佳方式使用Gson情況下從ReaderJsonReader閱讀(包括工作流與完美)來反序列化。這同樣適用於WriterJsonWriter

private static List<GameItem> readGameItemsFromFile(final File file) 
     throws IOException { 
    try (final InputStream inputStream = new FileInputStream(file); 
      final Reader reader = new BufferedReader(new InputStreamReader(inputStream))) { 
     // Note that this .fromJson overload: 
     // - does not require an intermediate string to be collected and then parsed (a common misuse of Gson parsing facilities) 
     // - specifies the target list element type because List.class is just a class, 
     return gson.fromJson(reader, listOfGamesTypeToken.getType()); 
    } 
} 

private static void writeGameItemsToFile(final List<GameItem> gameItems, final File file) 
     throws IOException { 
    try (final OutputStream outputStream = new FileOutputStream(file); 
      final Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream))) { 
     // Note that this .toJson overload: 
     // - allows to "calibrate" the source list type more precisely 
     // - does not require an intermediate JSON string collected into memory and then flushed to a file (another common misuse) 
     gson.toJson(gameItems, listOfGamesTypeToken.getType(), writer); 
    } 
} 

public static void main(final String... args) 
     throws IOException { 
    final File file = new File("gameItems.json"); 
    final List<GameItem> gameItems = readGameItemsFromFile(file); 
    // ... process the game items here ... 
    writeGameItemsToFile(gameItems, file); 
} 
+0

感謝您的幫助,但我得到這個錯誤。 '線程中的異常「主」com.google.gson。JsonSyntaxException:java.lang.IllegalStateException:期望BEGIN_ARRAY,但在BEGIN_OBJECT第1行第2列路徑$ \t at com.google.gson.Gson.fromJson(Gson.java:891) \t at com.google.gson.Gson。 fromJson(Gson.java:844) \t at org.fryslan.server.json.DataReader.readGameItemsFromFile(DataReader.java:31)' – Fryslan

+0

@Fryslan您是否試圖反序列化單個對象或列表?我上面的代碼希望根據您在問題中提供的JSON解析JSON,比如'[{...},{...},{...},...]'(一個對象數組)後來。它是否與你試圖解析的JSON文件相匹配? –

+0

我的不好..... 現在開始工作,謝謝一噸。 – Fryslan