在Java

时间:2019-07-02 22:01:16

标签: java list object gson dynamictype

我看到了许多匹配的问题,但没有回答我的问题。我想以一种不确定的方式使以下代码段动态化:我不确定我的API将返回单个对象还是对象数组。

List<Article> article = null;

我看到了以下类似的示例,但这不能回答我的问题:

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

问题是,我在Java gson 模型类中定义了article变量,但我真的不知道如何处理响应并使我的article动态地表现。因此,如果有单个对象,则它应像单个对象而不是List一样工作;如果有对象数组,则它应像List一样工作。

我也不确定类似的方法是否会起作用,但我正在寻找任何可行的形式的以下功能:

<T> Article article = null;

注意:我也看到了这个Generic Type Doc.,但这无助于解决我的问题。

2 个答案:

答案 0 :(得分:0)

请考虑使用内部执行聚合方法的方法扩展ArrayList,以便在外部使用相同数量的内部对象(无论是0、1,还是N个),其行为相同。

class Articles extends ArrayList<Article> {...}

答案 1 :(得分:0)

尽管@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之后

/**
 * 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;
    }
}

最后,我们将适配器注册到GSON模型中用于API响应的article字段中,并将其类型更改为ArticleList

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

请注意,任何单个Article响应都会自动添加为ArticleList作为列表元素。您可以通过更改read的{​​{1}}方法中的实现来更改此行为。

我希望这也会有所帮助。干杯!