【问题标题】:How do I get a foreign key's field using Retrofit and Gson?如何使用 Retrofit 和 Gson 获取外键字段?
【发布时间】:2016-05-29 12:49:40
【问题描述】:

我有一个 api 端点,它为事件表输出这个 json

{
    "name": "",
    "time": null,
    "event_pic_url": null,
    "description": "",
    "event_type": null,
    "invite_only": false,
    "free": false,
    "age_restriction": false,
    "ticket_price": null,
    "venue": null
}

场地字段是具有这种格式的场地表的外键。

{
    "name": "",
    "rating": null,
    "longitude": null,
    "latitude": null
}

获得事件列表后,我想将它们放在回收站视图上(我已经可以获取列表并知道如何使用适配器)但我不想显示场地的 {id},我想要使用场地的{name}。我该怎么做呢?是不是和嵌套的json如何反序列化有关?

【问题讨论】:

  • 视情况而定...我有几个问题,也许我可以提供帮助。你在使用 Gson 的改造吗?你的rest api实际上是返回上面的jsons还是序列化的结果?我的意思是,服务器是否有可能甚至没有向您发送嵌套的 json?你已经有一些模型了吗?
  • 是的,我正在使用 Gson 进行改造。如上所示,其余 api 返回 json。它不发送嵌套的 json。
  • 好的,改造不会为您开箱即用。您有 2 个选项,找出第一个调用是否支持某些参数,或者告诉服务器他还应该在响应中包含 venue json 的标头。如果是这样,那么提供帮助会更容易。如果没有,那么您必须找出如何获得 venue 的 id,因为很可能您将不得不再打一个休息电话。我会采用第一种方法,尝试弄清楚您是否可以在第一个呼叫的响应中包含venue 的正文。告诉我,我会进一步帮助你。
  • 我不确定我是否理解你所说的“找出第一个调用是否支持某些参数,或者告诉服务器他还应该包含场地的标头找出第一个调用是否支持某些参数的意思参数或标头,告诉服务器他也应该包括场地”你能给我一个这样的标头或参数的例子吗?
  • 这取决于您调用的 API,除了负责它的人之外没有人可以回答这个问题。如果您是端点的负责人,则将其更改为返回活动场地。

标签: android json gson retrofit retrofit2


【解决方案1】:

在所有的 cmets 之后,我假设现在你有类似的东西:

{
  "name": "",
  "time": null,
  "event_pic_url": null,
  "description": "",
  "event_type": null,
  "invite_only": false,
  "free": false,
  "age_restriction": false,
  "ticket_price": null,
  "venue": {
     "name": "",
     "rating": null,
     "longitude": null,
     "latitude": null
  }
}

由于您使用的是Gson,因此您需要以下型号

public class Venue {

  @SerializedName("name")
  @Expose
  private String name;
  @SerializedName("rating")
  @Expose
  private Integer rating;
  @SerializedName("longitude")
  @Expose
  private Double longitude;
  @SerializedName("latitude")
  @Expose
  private Double latitude;

  // ...
}

public class Event {

  @SerializedName("name")
  @Expose
  private String name;
  @SerializedName("time")
  @Expose
  private String time;
  @SerializedName("event_pic_url")
  @Expose
  private String eventPicUrl;
  @SerializedName("description")
  @Expose
  private String description;
  @SerializedName("event_type")
  @Expose
  private String eventType;
  @SerializedName("invite_only")
  @Expose
  private Boolean inviteOnly;
  @SerializedName("free")
  @Expose
  private Boolean free;
  @SerializedName("age_restriction")
  @Expose
  private Boolean ageRestriction;
  @SerializedName("ticket_price")
  @Expose
  private Double ticketPrice;
  @SerializedName("venue")
  @Expose
  private Venue venue;
  // ...
}

请注意,我在这里假设了一些数据类型,即 latitudelongitude 以及 event_type。因为在 json 中它们是 null 我不能确定,但​​我想你可以从这个例子中理解。另外请添加适当的 getter 和 setter。

我希望您专注于 venue 部分。如您所见,我基本上是在 Java 对象中重新创建“嵌套”json 部分。仅此而已,Gsonretrofit 将为您完成剩下的工作。就是这样。请注意 - 这可能会因您的工作方式而有很大差异。我更喜欢rxjava,但这里我会使用回调方法,因为它更容易解释。

改造1.9你可以这样做:

public interface EventService {
   @GET("/url/to/events/endpoint/")
   public void get(Callback<Event> callback);
}

如果一切顺利,在您的回调的 success 方法上,您将获得一个 Event 的实例,您可以在其中访问 Venue 对象,前提是返回的 json 实际上是上面的那个。

改造2界面略有变化,但本质上还是和以前一样:

public interface EventService {
   @GET("/url/to/events/endpoint/")
   public Call<Event> get();
}

一旦您enqueue 请求并定义Callback 对象,您还将在成功方法中获得一个Event 对象,该对象将引用一个场所。以下是使用 Retrofit 2 实现这些回调的方式(可能在不同的改造版本之间略有不同。我不完全记得了):

eventService.get().enqueue(new Callback<Event>() {
  @Override public void onResponse(Call<Event> call, Response<Event> response) {
    if (!response.isSuccessful()) {
      // Handle http error
      return;
    }

    Event event = response.body();
    Venue venue = event.getVenue();

    // do something with it
  }

  @Override public void onFailure(Call<Event> call, Throwable t) {
    // Handle error
  }
 });
}

这里eventServiceRetrofit.create(EventService.class)创建的对象。

同样,改造位可能会根据您要使用的方法而改变。重要的是要了解如何从 json 响应映射到 java 对象,基本上你只需要复制相同的 json 结构但在 java 对象中。希望对您有所帮助。

【讨论】:

  • 嗨。我能够更改我的改造代码,以便我可以反序列化嵌套的 json,但现在我在将场地名称绑定到 textview 时遇到问题。当我尝试设置如下文本时获得嵌套响应后:holder.eventVenueTextView.setText(event.getVenue().getName()),我得到一个 java.lang.NullPointerException,它指向上面的行。非嵌套字段工作正常,只是场地名称不起作用。我遵循了您的其他步骤,当我在改造中记录响应时,我可以看到一个具有场地的响应
  • 嘿,您能否更新您的问题或将我指向您拥有代码的链接?我猜java模型和json之间可能存在小的差异。如果您也可以放置新的 json 响应,那也将非常有帮助。
  • 谢谢。我能够解决问题。我没有添加转换器工厂,但是当我添加时一切正常。
猜你喜欢
  • 1970-01-01
  • 2016-04-09
  • 2014-12-28
  • 2020-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-06
相关资源
最近更新 更多