2017-02-03 4 views
0

Я пытаюсь создать кэш для игры с использованием файлов JSON. Запись и извлечение этих данных будет осуществляться с использованием GSON. У меня есть файл JSON, содержащий несколько объектов, внутри этих объектов хранятся и другие объекты.Извлечение вложенных объектов из файла JSON с использованием Gson

Мой вопрос: как получить эти данные наилучшим образом?

Объект 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 экземпляров) и могут быть легко разделяют глобально (но разумно).

  • Нанести буферные чтение и запись от и до I/O потоки

Лучшего способ десериализации с помощью Gson экземпляров читают из Reader или JsonReader (как работы с потоками отлично). То же самое относится к Writer и JsonWriter.

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

Спасибо за помощь, но я получаю эту ошибку. 'Исключение в теме" main "com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Ожидаемое BEGIN_ARRAY но BEGIN_OBJECT в строке 1 колонки 2 пути $ \t в com.google.gson.Gson.fromJson (Gson.java:891) \t в 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

ow my bad ..... Идите теперь, работая благодаря тонне. – Fryslan

Смежные вопросы