简体   繁体   English

Retrofit2 指定根元素并转换数据类型

[英]Retrofit2 Specify root element and convert datatype

I've just started working with Retrofit2 and the API I'm consuming wraps all valid responses in a "response" object as shown below.我刚刚开始使用 Retrofit2,我正在使用的 API 将所有有效响应包装在一个“响应”对象中,如下所示。 I need to tell Retrofit to parse only the values within response without actually nesting them inside another object.我需要告诉 Retrofit 只解析响应中的值,而不实际将它们嵌套在另一个对象中。 For the login code, I'm also faced with the issue of getting a String which I want to convert to an actual time stamp.对于登录代码,我还面临获取字符串的问题,我想将其转换为实际时间戳。

This is a sample response from a login request:这是来自登录请求的示例响应:

{  
   "status":"success",
   "response":{  
      "token":"test_token",
      "expires":"1485217863"
   }
}

In the above the only two actual values are:在上面只有两个实际值是:

token
expires 

I'm hoping to end up with something like what is shown below.我希望最终得到如下所示的结果。

public class Token {

  @SerializedName("token")
  String token;

  @SerializedName("expires")
  Timestamp expires;

  public User(String token, String expires ) {
    this.token
    this.expires = //conversion code omitted. 
  }
}

You have a couple of options here.你在这里有几个选择。 You can either use a custom serialiser/deserialiser, type adapters, or you can simply use pojos and unwrap the result yourself.您可以使用自定义序列化器/反序列化器、类型适配器,或者您可以简单地使用 pojos 并自己解包结果。

Let me start with the easiest solution I can think of.让我从我能想到的最简单的解决方案开始。 Picture you have these classes:图片你有这些类:

public class ResponseData<T> {
    @SerializedName("status")
    @Expose
    String status;
    @SerializedName("response")
    @Expose
    T response;

    public T getResponse() {
      return response;
    }
    // getters and setters and friends
}

public class Token {
    @SerializedName("token")
    @Expose
    String token;

    @SerializedName("expires")
    @Expose
    Timestamp expires;

    public Token(String token, String expires) {
        this.token = token;
        this.expires = expires;
    }
}

So one first thing to notice is the use of @Expose .所以首先要注意的是@Expose的使用。 This is a nice to have, but not extremely necessary.这是一个很好的拥有,但不是非常必要。 It helps you out when you have custom serialisers.当您有自定义序列化程序时,它会帮助您。

I assumed that you can have multiple api endpoints that return the same kind of body, where the json is:我假设您可以有多个 api 端点返回相同类型的主体,其中 json 是:

{  
 "status":"success",
 "response":{  
  // Can be anything
 }
}

And as you can see the response can be anything.正如您所见,响应可以是任何内容。

You can then make your retrofit calls return ResponseData<Token> and in your callbacks you can check the value of status and see if you can do getResponse to unpack the result.然后你可以让你的改造调用返回ResponseData<Token>并且在你的回调中你可以检查status的值,看看你是否可以执行getResponse来解压结果。 The advantage of this approach is that you can reuse ResponseData fairly easily.这种方法的优点是您可以相当轻松地重用ResponseData

Another approach is to use custom serialisers or type adapters.另一种方法是使用自定义序列化程序或类型适配器。 This is in my opinion more laborious, but still a valid approach.在我看来,这更费力,但仍然是一种有效的方法。 I think the answer here is quite extensive and explains how you can do this to get the nested object inside response .我认为这里的答案非常广泛,并解释了如何执行此操作以在response获取嵌套对象。

To prepare retrofit to use the type adapters, you'll need to inject a configured Gson instance into it.要准备改造以使用类型适配器,您需要将配置的Gson实例注入其中。 Here's how:就是这样:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(Token.class, new YourTypeAdapter())
    .create();

Retrofit retrofit = new Retrofit.Builder()
   .addConverterFactory(GsonConverterFactory.create(gson))
   // ....

As you can see, we pass the created gson with your type adapter to the GsonConverterFactory used by retrofit.如您所见,我们将创建的带有类型适配器的GsonConverterFactory给改造使用的GsonConverterFactory This prepares retrofit to serialise and deserialise Token objects using the given type adapter.这准备改造以使用给定的类型适配器序列化和反序列化Token对象。

I think the main disadvantage with this approach is that if you want to write a generic deserialiser/serialiser/typeadapter it can become complicated quite fast (assuming you won't have only a Token object).我认为这种方法的主要缺点是,如果你想编写一个通用的反序列化器/序列化器/类型适配器,它会很快变得复杂(假设你不会只有一个Token对象)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM