Gson: Как написать десериализатор для связанных объектов - PullRequest
0 голосов
/ 03 апреля 2020

Представьте себе следующее JSON для библиотеки книг:

{
    "books": [{
            "id": 562,
            "name": "This is a booktitle"
        },
        {
            "id": 875,
            "name": "This is another booktitle"
        }
    ]
}

Чтобы получить больше информации о первой книге, я могу просто подать запрос https://thislibrarydoesnotexists.com/books/562, который вернет следующее JSON:

{
    "name": "This is a booktitle",
    "pages": 137,
    "blurp": "This book is about the booktitle",
    "authors": [{
        "name": "Generic Author",
        "id": 78
    }]
}

Теперь я могу запросить дополнительную информацию об авторе, используя запрос https://thislibrarydoesnotexists.com/authors/78, и эта игра будет включаться go довольно долго, пока я не получу всю информацию.

Сейчас моя цель состоит в том, чтобы иметь следующую java структуру класса:

class Library{
    List<Book> books
}

class Book{
    String name;
    int pages;
    String blurp;
    List<Author> authors;
}

class Author{...}

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

final Gson defaultGson = new GsonBuilder.create();
GsonBuilder gsonBuilder = new GsonBuilder();    
gsonBuilder.registerTypeAdapter(Book.class, new JsonDeserializer<Book>() {

    @Override
    public Skill deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                    throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();
        if(jsonObject.has("id")) { //It is just a link to a book
            String bookJson = getJson("https://thislibrarydoesnotexists.com/books/" + jsonObject.get("id").getAsInt());
            Book book = gson.fromJson(bookJson, Book.class);
            return book;
        }else { 
            Book book = defaultGson.fromJson(json, Book.class); //#1
            return book;
        }
    }


}); 
gson = gsonBuilder.create(); 

Это решение не выполнено на # 1, поскольку пользовательский десериализатор для авторов не будет использован.

Как правильно решить эту проблему?

  • Создать объект Book вручную в другом случае? // Много работы для сложного API
  • Использовать несколько Gsons с какой-то иерархией Gson? // Ужасно и не будет работать при наличии циклических c зависимостей
  • Использовать класс-оболочку? // Просто безобразно, но должно работать

1 Ответ

0 голосов
/ 03 апреля 2020

Измените List<Book> books на List<BookSummary> books, поскольку объект, возвращаемый для одной книги, не совпадает с объектом, возвращенным в списке книг.

class BookSummary {
    int id;
    String name;
}

не совпадает с

class BookDetail {
    String name;
    int pages;
    String blurp;
    List<Author> authors;
}

Нет необходимости в (де) сериализаторе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...