简体   繁体   English

Retrofit2处理包含两个模型数据的JSON响应

[英]Retrofit2 handle JSON response that contains two models data

I'm using retrofit2 to handle http request after calling from API. 从API调用后,我正在使用Retrofit2处理http请求。 Let me explain this. 让我解释一下。

I have 2 java class(POJO) created to handle user and lecturer data which is User.java and Lecturer.java respectively. 我有2个 Java类(POJO)创建来处理用户和讲师数据,分别是User.javaLecturer.java For the response data such as : 对于响应数据,例如:

{
  "users": [
    {
      "user_id": "28",
      "user_email": "john@abc.com",
      "user_password": "123"
    }
  ]
}

i can use User.java class to handle this response. 我可以使用User.java类来处理此响应。 Nothing complex in this file, only contains getter and setter method. 该文件没有什么复杂的,仅包含gettersetter方法。 Same goes to lecturer data, here is the example of lecturer data : 讲师数据也是如此,这是讲师数据的示例:

{
  "lecturers": [
    {
      "lecturer_id": "3",
      "user_id": "28",
      "lecturer_name": "johny2"
    }
  ]
}

i can handle it by using Lecturer.java class. 我可以通过使用Lecturer.java类来处理它。

But the problem is, if the response contains both user and lecturer data on a single json, how to handle it?? 但是问题是,如果响应在单个json上同时包含用户和演讲者数据,该如何处理? . Here is the example of request : 这是request的示例:

{
  "users": [
    {
      "user_id": "28",
      "user_email": "john@abc.com",
      "user_password": "123",
      "lecturer_id": "3",
      "lecturer_name": "johny2"
    }
  ]
}

To solve this problem, i think i need to create another java class that contains both User and Lecturer class on it, unfortunately at here i'm stuck. 为了解决这个问题,我想我需要创建另一个同时包含UserLecturer类的java类,不幸的是在这里我被卡住了。

This is new file, that i tried to create (Userlecturer.java) : 这是我尝试创建的新文件(Userlecturer.java)

public class UserLecturer {

  User user;
  Lecturer lecturer;

  // how to implement on this part
}

Here is UserLecturer interface : 这是UserLecturer界面:

public interface UserLecturerInterface {

  @GET ( "api/endpoint/here" )
  Call<UserLecturer> getLecturerByUserId (@Path( "userId" ) String userId );

}

Appreciated for any helps. 感谢任何帮助。 Ask me for more inputs if above use case did't clear enough. 如果上述用例还不够清楚,请询问我更多信息。 Thanks 谢谢

I think the POJO should be: 我认为POJO应该是:

public class Users {
    String userId;
    String userEmail;
    String userPassword;
    String lecturerId;
    String lecturerName;
}

Even though there are 2 models inside the JSON, you only need 1 model for Retrofit. 即使JSON中有2个模型,您也只需要1个模型即可进行翻新。


If you really want to split the 1 JSON response into 2 models, I think you have to implement custom JSON converter. 如果您确实要将1个JSON响应拆分为2个模型,我认为您必须实现自定义JSON转换器。

Gson gson = new GsonBuilder()
            .registerTypeAdapter(UserLecture.class, new JsonDeserializer<UserLecture>() {
                public UserLecture deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                    JsonArray usersJsonArray = json.getAsJsonObject().getAsJsonArray("users");
                    JsonObject userJsonObject = usersJsonArray.getAsJsonArray().get(0).getAsJsonObject();
                    User user = new User();
                    user.setUserId(userJsonObject.get("user_id").getAsString());
                    user.setUserEmail(userJsonObject.get("user_email").getAsString());
                    user.setUserPassword(userJsonObject.get("user_password").getAsString());
                    Lecturer lecturer = new Lecturer();
                    lecturer.setLecturerId(userJsonObject.get("lecturer_id").getAsString());
                    lecturer.setLecturerName(userJsonObject.get("lecturer_name").getAsString());
                    return new UserLecture(lecturer, user);
                }
            })
            .create();

Retrofit retrofit = new Retrofit.Builder()
.baseUrl([YOUR_BASE_URL])
.addConverterFactory(GsonFactoryConverter.create(gson))
.build();

This is some code I use to convert longs to Java Date objects. 这是一些我用来将long转换为Java Date对象的代码。 Presumably, you can do the same thing for your UserLecture object. 大概,您可以对UserLecture对象执行相同的操作。 You should be able to extract the individual json objects for User and Lecture, create a new UserLecture object and let User and Lecture as objects in it. 您应该能够为User和Lecture提取单个json对象,创建一个新的UserLecture对象,并将User和Lecture作为对象。

Gson gson = new GsonBuilder().registerTypeAdapter(UserLecture.class, new JsonDeserializer<UserLecture>() {
            public UserLecture deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
                JsonObject user = json.getAsJsonObject().getAsJsonObject("user");
                JsonObject lecture = json.getAsJsonObject().getAsJsonObject("lecture");
                return new UserLecture(user, lecture);
            }
        }).create();

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com")
    .addConverterFactory(GsonFactoryConverter.create(gson))
    .build();

Then inside UserLecture : 然后在UserLecture内部:

public UserLecture(JsonObject userJson, JsonObject lectureJson) {
   this.user = new User();
   this.user.setUserId(userJson.get("user_id").getAsInt());
   this.user.serUserEmail(userJson.get("user_email").getAsString());
   //so on.
}

At first let me say that the JSON you need to process here is broken by design so you should urge the guy / department / company to fix it. 首先,让我说,您需要在此处处理的JSON被设计破坏了,因此您应该敦促人员/部门/公司对其进行修复。

Secondly, JSON processors like Jackson allow to parse polymorphic data structures like this easily, but they require some kind of type flag to distinguish one of another type (ie type: "user" and type: "lecturer" ). 其次,像Jackson这样的JSON处理器允许轻松地解析这样的多态数据结构,但是它们需要某种type标志来区分另一种类型(即type: "user"type: "lecturer" )。 There is also a way to do this without such type flags, but there is a lot more hand work involved. 也可以通过不使用此类type标志的方式来执行此操作,但是需要进行大量手工操作。 The last example here shows how to do it. 这里最后一个示例显示了如何执行此操作。

Yes, it is one possible solution. 是的,这是一种可能的解决方案。 Gson ignores all fields, which names doesnt match @SerializedName annotation. Gson会忽略所有名称与@SerializedName注释不匹配的字段。 So, you may try another solution without creating any more pojo classes- return result as String, and try to parse this string as both classes. 因此,您可以尝试其他解决方案而无需创建更多pojo类-将结果作为String返回,并尝试将此字符串解析为两个类。 If one result is empty- then you have another. 如果一个结果为空-那么您将得到另一个。 But, if both kbjects isnt empty- then original response contain fields from both pojos 但是,如果两个kbject都不为空,则原始响应包含来自两个pojos的字段

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

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