Java Gson - Json сериализаторы и десериализаторы, использующие шаблоны проектирования? - PullRequest
1 голос
/ 12 марта 2020

Я работаю над настольным музыкальным c приложением игрока. Я решил хранить всю необходимую информацию о песнях, музыкальных списках воспроизведения c et c. внутри json файла.

У меня есть библиотека классов, которая, вообще говоря, отвечает за подготовку песен и обработку файла json.

public class Library {

    private static File libFile;
    private static SongList songList;
    private static List<Album> albumList;
    private static List<Artist> artistList;
    private static List<Playlist> playlistList;
    ...
}

Мне нужно сериализовать эти 4 классы, которые содержатся внутри библиотеки:

public class SongList {
    protected SimpleStringProperty title;
    protected List<Song> songs;
    ...
}

public class Album extends SongList implements Comparable<Album> {

    private SimpleStringProperty artist;
    private int releaseYear;
    private long lengthInSeconds;
    private Image cover;
    private SimpleObjectProperty<Image> coverProperty;
    private int id;
    ...
}

public class Playlist extends SongList implements Comparable<Playlist>{ 
    ... 
}

public class Artist implements Comparable<Artist>{

    private SimpleStringProperty name;
    private List<Album> albums;
    ...
}

(* NOTE) для сериализации SongList. Я использую сериализацию по умолчанию с использованием пакета fx-gson, поэтому объекты свойств не такие подробные.

Wanted json структура файла:

{
  "songlist": {
    "title": "main.songlist",
    "songs": [
      {
        "title": "songtitle",
        "artist": "artistname",
        "album": "albumname",
        "length": "4:09",
        "lengthInSeconds": 249,
        "playCount": 0,
        "directory": "directory",
        "id": 0
      },
      {
        "title": "songtitle",
        "artist": "artistname",
        "album": "albumname",
        "length": "4:09",
        "lengthInSeconds": 249,
        "playCount": 0,
        "directory": "directory",
        "id": 1
      }
    ]
  },
  "playlistList": {
    "playlist1": [
      0,
      1
    ],
    "playlist2": [
      0,
      1
    ]
  },
  "albums": {
    "Album name": {
      "id": 10,
      "artist": "artist",
      "release.year": 2019,
      "length.in.seconds": 786,
      "songs": [
        0,
        1
      ]
    }
  },
  "artistList": {
    "artist name1":[
      10
    ]
  }
}

Существует 2 основных метода, отвечающих за обработку файла: Library.load () и Library.save (). Например, метод save использует пару методов, отвечающих за сохранение альбомов, списков воспроизведения или коллекций исполнителей, таких как этот:

private static <T extends SongList> JsonElement parseSongList(List<T> list) {

    GsonBuilder customGsonBuilder = new GsonBuilder();

    //Custom serializer for songlist (id only)
    JsonSerializer <SongList> playlistSerializer = new JsonSerializer<SongList>(){
        @Override
        public JsonElement serialize(SongList src, Type type, JsonSerializationContext context) {
            JsonArray ids = new JsonArray();
            for(Song song : src.get()) {
                ids.add(song.getId());
            }
            return ids;
        };
    };


    //Custom serializer for albums
    JsonSerializer <Album> albumSerializer = new JsonSerializer<Album>() {
        @Override
        public JsonElement serialize(Album src, Type type, JsonSerializationContext context) {
            JsonObject result = new JsonObject();
            result.addProperty("id", src.getId());
            result.addProperty("artist", src.getArtist().get());
            result.addProperty("release.year", src.getReleaseYear());
            result.addProperty("length.in.seconds", src.getLengthInSeconds());

            JsonArray ids = (JsonArray) playlistSerializer.serialize(src, type, context);
            result.add("songs", ids);
            return result;
        }
    };

    //Selecting type adapter
    if(!list.isEmpty()) {
        SongList tmp = list.get(0);
        if(tmp instanceof Playlist) {
            customGsonBuilder.registerTypeAdapter(Playlist.class, playlistSerializer);
        }else if(tmp instanceof Album) {
            customGsonBuilder.registerTypeAdapter(Album.class, albumSerializer);
        }
    }else {
        return null;
    }

    Gson customGson = customGsonBuilder.setPrettyPrinting().create();

    //serializing
    JsonObject songs = new JsonObject();
    for(SongList songlist : list) {
        songs.add(songlist.getTitle(), customGson.toJsonTree(songlist));
    }

    return songs;

}

Как вы можете видеть, он грязный (я думаю) и даже не самый грязный. Каждый метод загрузки / сохранения предоставляет разные сериализаторы и десериализаторы для разных структур.

Я бы хотел провести "общую очистку" в классе Библиотеки, чтобы его было легко читать, поддерживать и гарантировать, что при необходимости я могу легко добавить больше структур или функций musi c.

Вот мои вопросы:

  1. Каждый объект списка песен, списка воспроизведения, альбома или исполнителя сводится к LinkedList<Songlist> - есть ли какой-либо предпочтительный способ сериализации и десериализации этих структур или не имеет значения? Должен ли я предоставить сериализаторы и десериализаторы для Songlist / Album / Artist или для List<Songlist>?

  2. Я хочу содержать все объекты, методы, классы и т. Д. c. отвечает непосредственно за сериализацию / десериализацию в одном модуле (класс / пакет или что-то еще). Я никогда не использовал один, но есть ли шаблон дизайна, который подойдет для моего приложения (заводской метод?). Если да, я был бы очень благодарен за предоставление мне какого-то общего плана (или ссылки на руководство), которому я должен следовать для его реализации.

  3. Какие-либо общие советы о структурах Библиотеки?

Любые другие предложения о структуре кода / проекта приветствуются, возможно, есть много проблем.

...