динамически определять коллекцию или переменную типа объекта в Java - PullRequest
0 голосов
/ 03 июля 2019

Я видел несколько подходящих вопросов, но не ответил на мою проблему. Я хочу, чтобы следующий фрагмент кода был динамичным, и я не уверен, что мой API вернет один объект или массив объектов.

List<Article> article = null;

Я видел разные примеры, как показано ниже, но это не отвечает на мой вопрос:

List<Animal> animals = new ArrayList<>();

Дело в том, что в моем классе модели Java gson определена переменная article, и я действительно не представляю, как я могу обработать ответ и заставить мой article вести себя динамически. Таким образом, если существует один объект, то он должен действовать как отдельный объект вместо List, а если существует массив объектов, то он должен действовать как List.

Я также не уверен, будет ли что-то подобное работать или нет, но я ищу следующий тип функциональности в любой доступной форме:

<T> Article article = null;

Примечание: я также видел этот универсальный док. , но это не помогает решить мою проблему.

Ответы [ 2 ]

0 голосов
/ 03 июля 2019

Хотя ответ @Jeff Stewart может быть жизнеспособным решением, я бы хотел кое-что добавить.Если безопасность типов не является проблемой для ваших нужд, вы также можете определить переменную article как Object.Тем не менее, вы должны проверить свою переменную позже, когда вы используете, что-то вроде:

if(article instanceof Collection){
  // article is an array of objects  
} else {
  // article is a single object
}

ОБНОВЛЕНИЕ: Благодаря идее @Jeff Stewart я реализовал более подходящее решение, которое может обрабатывать как одини несколько значений в одном типе.

Учитывая ваш ответ API примерно так:

"article": {"name":"article1",...} 
 - or -  
"article": [{"name":"article1",...}, {"name":"article2",...}]

Давайте создадим ArticleList, полученный из java.util.ArrayList

/**
 * Custom type to handle both single Article and ArrayList<Article> types
 *
 * @author Yavuz Tas
 *
 */
public class ArticleList extends ArrayList<Article> {

}

После того, как мы реализуем пользовательский JsonAdapterдля ArticleList type

/**
 * Custom JsonAdapter for GSON to handle {@link ArticleList} converstion
 * 
 * @author Yavuz Tas
 *
 */
public class ArticleListJsonAdapter extends TypeAdapter<ArticleList> {

    /*
     * We just create another instance of GSON here in order to reuse their
     * predefined object and collection adapters
     */
    private static final Gson gson = new Gson();
    private static final TypeAdapter<Article> objectTypeAdapter = gson.getAdapter(Article.class);
    private static final TypeAdapter<List<Article>> listTypeAdapter = gson.getAdapter(new TypeToken<List<Article>>() {
    });

    @Override
    public void write(JsonWriter out, ArticleList list) throws IOException {

        /*
         * Since we do not serialize ArticleList by gson we can omit this part but
         * anyway we can simply implement by reusing listTypeAdapter
         */
        listTypeAdapter.write(out, new ArrayList<Article>(list));

    }

    @Override
    public ArticleList read(JsonReader in) throws IOException {

        ArticleList deserializedObject = new ArticleList();

        // type of next token
        JsonToken peek = in.peek();

        // if the json field is single object just add this object to list as an
        // element
        if (JsonToken.BEGIN_OBJECT.equals(peek)) {
            Article object = objectTypeAdapter.read(in);
            deserializedObject.add(object);
        }

        // if the json field is array then implement normal array deserialization
        if (JsonToken.BEGIN_ARRAY.equals(peek)) {
            List<Article> list = listTypeAdapter.read(in);
            deserializedObject.addAll(list);
        }

        return deserializedObject;
    }
}

И, наконец, мы регистрируем наш адаптер в поле article в модели GSON, которое используется для ответа API, и меняем его тип на ArticleList:

@JsonAdapter(value = ArticleListJsonAdapter.class)
@SerializedName("article")
@Expose
private ArticleList article;

Обратите внимание, что любой отдельный ответ Article автоматически добавляется к ArticleList в качестве элемента списка.Вы можете изменить это поведение, изменив реализацию в read методе ArticleListJsonAdapter.

Надеюсь, это тоже поможет.Ура!

0 голосов
/ 03 июля 2019

Рассмотрите возможность расширения ArrayList с помощью методов, которые внутренне выполняют методы агрегирования, чтобы внешне он вел себя одинаково, независимо от того, существует ли 0, 1 или число N внутренних объектов.

class Articles extends ArrayList<Article> {...}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...