Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Android上使用TypeAdapter对数组或对象进行改造,深度为两级_Android_Gson_Retrofit2 - Fatal编程技术网

在Android上使用TypeAdapter对数组或对象进行改造,深度为两级

在Android上使用TypeAdapter对数组或对象进行改造,深度为两级,android,gson,retrofit2,Android,Gson,Retrofit2,我正在努力使用TypeAdapter。实际上,对于json字段,我可以有一个数组(当它为空时)或一个对象(当它不为空时)。这是无法改变的 以下是收到的JSON: { "notifications": [ { ... } ], "meta": { "pagination": { "total": 13, "count": 13, "

我正在努力使用TypeAdapter。实际上,对于json字段,我可以有一个数组(当它为空时)或一个对象(当它不为空时)。这是无法改变的

以下是收到的JSON:

{
    "notifications": [
        {
            ...
        }
    ],
    "meta": {
        "pagination": {
            "total": 13,
            "count": 13,
            "per_page": 20,
            "current_page": 1,
            "total_pages": 1,
            "links": []
        }
    }
}
相关字段是
链接
,您可以看到该字段位于
分页
中,该字段位于
中。这就是我的问题,我不知道TypeAdapter如何处理两个深度级别的
链接

我用它开始构建一个解决方案。这是:

我的自定义TypeAdapter类:

public class PaginationTypeAdapter extends TypeAdapter<Pagination> {

    private Gson gson = new Gson();

    @Override
    public void write(JsonWriter out, Pagination pagination) throws IOException {
        gson.toJson(pagination, Links.class, out);
    }

    @Override
    public Pagination read(JsonReader jsonReader) throws IOException {

        Pagination pagination;

        jsonReader.beginObject();

        if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) {
            pagination = new Pagination((Links[]) gson.fromJson(jsonReader, Links[].class));
        } else if(jsonReader.peek() == JsonToken.BEGIN_OBJECT) {
            pagination = new Pagination((Links) gson.fromJson(jsonReader, Links.class));
        } else {
            throw new JsonParseException("Unexpected token " + jsonReader.peek());
        }

        return pagination;
    }
}
目前我的错误是:
com.google.gson.JsonParseException:Unexpected-token-NAME

所以我知道我做得不对,因为我在用分页构建我的Gson。但我不知道该怎么处理。使用带有
meta
的TypeAdapter


欢迎任何帮助,谢谢

当您实现自定义类型适配器时,请确保您的类型适配器具有均衡的令牌读写:如果您打开一个类似于
[
]
的复合令牌对,则必须将其关闭(同时适用于
JsonWriter
JsonReader
)。您不需要这一行来解决您的问题:

jsonReader.beginObject();
因为它将
JsonReader
实例移动到下一个令牌,所以
BEGIN\u OBJECT
之后的下一个令牌要么是
NAME
要么是
END\u OBJECT
(在您的情况下肯定是前者)


备选方案#1 我还建议不要使用特别的
Gson
对象安装——这不会在
Gson
实例之间共享配置(例如,您的“全局”Gson
注册了许多自定义适配器,但此内部适配器没有任何配置,因此您的(反)序列化结果可能非常意外)。为了克服这个问题,只需使用比“免费”Gson实例更能感知上下文的
TypeAdapterFactory

final类分页TypeAdapterFactory
实现TypeAdapterFactory{
私有静态最终类型适配器工厂paginationTypeAdapterFactory=新paginationTypeAdapterFactory();
专用分页TypeAdapterFactory(){
}
静态TypeAdapterFactory getPaginationTypeAdapterFactory(){
返回paginationTypeAdapterFactory;
}
@凌驾
公共类型适配器创建(最终Gson Gson、最终TypeToken TypeToken){
//类可以使用==和进行比较=
if(typeToken.getRawType()!=Pagination.class){
//不分页?让格森挑选下一个最佳匹配
返回null;
}
//这里我们获得了两种类型适配器的引用:
//-这就是Gson.fromJson在引擎盖下的作用
//-我们为进一步(反)序列化节省了一些时间
//-您的课程要求不得超过其要求
最终类型适配器linksTypeAdapter=gson.getAdapter(Links.class);
final-TypeAdapter-linksArrayTypeAdapter=gson.getAdapter(Links[].class);
@抑制警告(“未选中”)
final TypeAdapter TypeAdapter=(TypeAdapter)新分页TypeAdapter(linksTypeAdapter,linksArrayTypeAdapter);
返回类型适配器;
}
私有静态最终类PaginationTypeAdapter
扩展类型适配器{
专用最终类型适配器链接类型适配器;
专用最终类型适配器链接RayTypeAdapter;
专用分页类型适配器(最终类型适配器链接StypeAdapter,最终类型适配器链接RayTypeAdapter){
this.linksTypeAdapter=linksTypeAdapter;
this.linksArrayTypeAdapter=linksArrayTypeAdapter;
}
@凌驾
公共无效写入(最终JsonWriter out、最终分页分页)
抛出IOException{
linksTypeAdapter.write(out,pagination.links);
}
@凌驾
公共分页读取(中的最终JsonReader)
抛出IOException{
最终JsonToken标记=in.peek();
//开关更好一些:您可以让IDE或静态分析器检查是否涵盖了所有情况
交换机(令牌){
案例开始\u数组:
返回新分页(linksArrayTypeAdapter.read(in));
案例开始对象:
返回新分页(linksTypeAdapter.read(in));
案例结束单元阵列:
案例结束对象:
案例名称:
大小写字符串:
案件编号:
大小写布尔值:
大小写为空:
案例结束文件:
//MalformedJsonException(不确定)可能更好,因为它是一个IOException,read方法抛出IOException
抛出新的MalformedJsonException(“意外标记:“+token+”位于“+in”);
违约:
//也许有一天,格森会在这里添加更多的东西……让我们做好准备
抛出新断言错误(令牌);
}
}
}
}

备选方案#2
你可以注释你的
私人链接@JsonAdapter
编码>并将类型适配器工厂直接绑定到链接:
Gson
links
对象直接“注入”到
Pagination
实例,因此您甚至不需要在那里使用构造函数。

在这里签出以了解如何处理Awesome!!只需删除一行代码就可以了。我应该更清楚TypeAdapter是如何工作的。非常感谢你的帮助。我也会检查您的备选方案:)
public class Pagination {

    private int total;

    private int count;

    @SerializedName("per_page")
    private int perPage;

    @SerializedName("current_page")
    private int currentPage;

    @SerializedName("total_pages")
    private int totalPages;

    private Links links;


    Pagination(Links ... links) {
        List<Links> linksList = Arrays.asList(links);
        this.links = linksList.get(0);
    }
}
Gson gson = new GsonBuilder().registerTypeAdapter(Pagination.class, new PaginationTypeAdapter()).create();