Retrofit Android:如何映射一组值?

时间:2017-08-27 11:05:52

标签: java json serialization retrofit2

端点返回如下的JSON响应。

{
   "students":[
      [
         1,
         "Tom",
         18,
         "USA"
      ],
      [
         2,
         "Linda",
         21,
         "Mexico"
      ]
   ],
   "other":[
      "100",
      "400"
   ]
}

让我们说我只关心回复中的students,并希望得到一份学生名单。在回复中,每个学生都被表示为没有键的值数组:

[id, name, age, country]

(假设可以有更多字段,但每个学生的字段顺序相同)

class GetStudentsResponse {
  Student[] students;
}

class Student {
  String name;
  int age;
  // HOW CAN I TELL RETROFIT TO MAP CORRECTLY HERE?
}

2 个答案:

答案 0 :(得分:0)

Retrofit本身没有进行JSON(反)序列化 - 它使用另一个库,默认情况下是GSON。

在您拥有的输入中,您实际上有一个数组([id, name, age, country]),因此您无法使用GSON默认生成的序列化程序将其解析为对象(您需要具有JSON对象)。

在这种情况下,您可以将该数组解析为String[]并将其解析为Student为该输入编写您自己的GSON序列化程序。我会推荐第二种解决方案:

JsonSerializer<Student> serializer = new JsonSerializer<Merchant>() {  
    @Override
    public JsonElement serialize(Student src, Type typeOfSrc, JsonSerializationContext context) {
        // Implement serializer here
    }
};


JsonDeserializer<Student> serializer = new JsonDeserializer<Student>() {  
    @Override
    public JsonElement deserialize(Student src, Type typeOfSrc, JsonSerializationContext context) {
        // Implement deserializer here
    }
};

您可以这样使用它:Gson gson = new GsonBuilder().registerTypeAdapter(Student.class, serializer).create();

另一种方法是创建TypeAdapter。以下是Gson documentation的示例:

 public class PointAdapter extends TypeAdapter<Point> {
   public Point read(JsonReader reader) throws IOException {
     if (reader.peek() == JsonToken.NULL) {
       reader.nextNull();
       return null;
     }
     String xy = reader.nextString();
     String[] parts = xy.split(",");
     int x = Integer.parseInt(parts[0]);
     int y = Integer.parseInt(parts[1]);
     return new Point(x, y);
   }
   public void write(JsonWriter writer, Point value) throws IOException {
     if (value == null) {
       writer.nullValue();
       return;
     }
     String xy = value.getX() + "," + value.getY();
     writer.value(xy);
   }
 }

答案 1 :(得分:0)

改造2。 当端点响应主体以数组开始时,例如:

[
 {"name": "John",
  "email": "john@example.com"
 },
 {"name": "Jess",
  "email": "jess@example.com"
 },
 ...
]

您可以使用以下方法:

<强> User.java

public class User {
    public String name;
    public String email;
}

接口:例如的 InterfaceAPI.java

public interface InterfaceAPI {
    @GET("users")
    Call<List<User>> getUsers();
}

数据提供者类:

    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://api.example.com")
        .client(okHttpClient)
        .build();

    InterfaceAPI retrofitAPI = retrofit.create(InterfaceAPI);
    Call<List<User>> call = interfaceAPI.getUsers();

    call.enqueue(new Callback<RegistrationResponse>() {
        @Override
        public void onResponse(@NonNull Call<List<User>>call, @NonNull Response<List<User>> response) {
            if (response.isSuccessful()) {
                // your code

            } else {
                // your code
            }
        }

        @Override
        public void onFailure(@NonNull Call<List<User>> call, @NonNull Throwable t) {
            //TODO
        }
    });

See here more examples.