Модификация: анализатор Json в соответствии с ответом - PullRequest
0 голосов
/ 25 сентября 2018

У меня есть служба REST, и ее ответ может быть изменен в зависимости от статуса.Например;При отправке запроса и ответа могут быть два типа.Первый такой как

{
  "status": "success",
  "user": {
    "user_id": 3554,
    "full_name": "test",
    "email_address": "test@test1.com",
    "end_date": null
  }
}

Второй тип такой:

{
  "status": "failure",
  "reason": "email_taken"
}

Ответ в соответствии с «статусом», который приходит с ответом.Я искал эту проблему и нашел некоторые решения (пользовательский конвертер, установить пользовательский конвертер и т. Д.), Но я думаю, что они не достаточно ясны.Есть ли такое решение?если «состояние» является успешным, преобразовать в ответ json в модель пользователя, иначе преобразовать ответ json в FailureModel?

Зависимость модификации: реализация 'com.squareup.retrofit: retrofit: 1.9.0'

Если единственным решением является пользовательский конвертер, пожалуйста, объясните это ясно, потому что я действительно новичок в этой теме.

Ответы [ 4 ]

0 голосов
/ 25 сентября 2018

С вашей модификацией 2.0 лучше всего использовать конвертер Gson.Просто добавьте аннотацию @Nullable с помощью дополнительного ключа json (в вашем случае пользователя и причины), чтобы он не зависал при разборе или не генерировал исключение нулевого указателя.Итак, ваш модельный класс выглядит следующим образом.

public class YourModelClass {

    @SerializedName("status")
    @Expose
    public String status;
    @Nullable
    @SerializedName("user")
    @Expose
    public User user;

    @Nullable
    @SerializedName("reason")
    @Expose
    public String reason;

    public class User {

    @SerializedName("user_id")
    @Expose
    public Integer userId;
    @SerializedName("full_name")
    @Expose
    public String fullName;
    @SerializedName("email_address")
    @Expose
    public String emailAddress;
    @SerializedName("end_date")
    @Expose
    public Object endDate;

    }
}

В вашей Деятельности или фрагменте, где вы запрашиваете, проанализируйте его следующим образом

@Override
    public void onResponse(Call<YourModelClass> call, Response<YourModelClass> response) {
        if(response.body.yourModelClass.status.equals("succ")) {
            User changesList = response.body().user;
            //perform action with user data
        } else {
           Log.d("failer", response.body().reason)
        }
    }

    @Override
    public void onFailure(Call<YourModelClass> call, Throwable t) {
        t.printStackTrace();
    }

Я надеюсь, что это сработает для вас.Используйте Android Studio плагин DTO Genrater для создания pojo.

0 голосов
/ 25 сентября 2018

Для этого вы можете использовать класс захвата, например:

public class Foo {
    String    status;
    String    reason;
    UserModel user;
    // Constructors, getter/setter, others
    // ...
}

, затем вызвать Retrofit как,

Call<Foo> callToYourAPI();

и когда вы хотите иметь пользователя:

if (foo.reason == "success") // or if (foo.user != null)
    // do something with foo.user

В этом случае преобразование выполняется автоматически.Если у вашей проблемы было поле, которое может быть одного типа или другого, вам понадобился бы конвертер.

0 голосов
/ 25 сентября 2018

Это возможно с помощью специального десериализатора JSON.У вас есть пользователь, только если статус успешен, если у вас нет причины.В случае, если у вас есть ошибка статуса и вы пытаетесь получить доступ к ее нулю.

public class CustomConvertor implements JsonDeserializer<Response> {

    @Override
    public Response deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

        Gson gson = new Gson();
        Response response = gson.fromJson(json, Response.class);

        if (response.getStatus().equals("success")) {
            // The full response as a json object
            final JsonObject jsonObject = json.getAsJsonObject();
            // The user attribute in the JSON received
            final JsonElement jsonElement = jsonObject.get("user");

            User user = gson.fromJson(jsonElement, User.class);
            response.setUser(user);
        }else{
            // you could do this
            // not needed as json is deserialized to Response already
            // just for the example
            final JsonObject jsonObject = json.getAsJsonObject();
            String reason = jsonObject.getAsJsonPrimitive("reason").getAsString();
            response.setReason(reason);
        }

        return response;
    }
}

Модифицированная часть

GsonBuilder gsonBuilder =new  GsonBuilder();
gsonBuilder.registerTypeAdapter(Response.class, new CustomConvertor());
Gson gson = gsonBuilder.create();
GsonConverterFactory gsonConverterFactory = GsonConverterFactory.create(gson);
Retrofit retrofit = new Retrofit.Builder()
         ...// other setups
        .addConverterFactory(gsonConverterFactory).build();

Затем

// service is my case
Service service = retrofit.create(Service.class);
// call enqueue in your case.for testing i used mockwebserver
Response response = service.exampleJson().execute().body();
Log.i("User: ","" + response.geUser().getFullname());

в случае ошибки

Log.i("Error: ","" + response.getReason());

Вы можете получить свои pojos от http://www.jsonschema2pojo.org/

Pojo's

Response.java

public class Response {

    @SerializedName("status")
    @Expose
    private String status;
    @SerializedName("user")
    @Expose
    private User user;

    @Expose
    @SerializedName("reason")
    private String reason;

    public void setReason(String reason) {
        this.reason = reason;
    }

    public String getReason() {
        return reason;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }    
}

User.java

public class User {

    @SerializedName("user_id")
    @Expose
    private int userId;
    @SerializedName("full_name")
    @Expose
    private String fullName;
    @SerializedName("email_address")
    @Expose
    private String emailAddress;
    @SerializedName("end_date")
    @Expose
    private Object endDate;

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }

    public Object getEndDate() {
        return endDate;
    }

    public void setEndDate(Object endDate) {
        this.endDate = endDate;
    }
}

Другой способ

Call<Response> auth = .// setup
        auth.enqueue(new Callback<Response>() {
            @Override
            public void onResponse(Call<Response> call, Response<Response> response) {
                if (response.isSuccessful() ) {
                      Response respojo = response.body();
                     if(respojo.getStatus().equals("success"){
                         Log.i("User: ","" + respojo.getUser().getFullname());
                      }else {
                         Log.i("Error: ","" + respojo.getReason());
                      }  
                    }
                } else {
                   response.errorBody(); 

                }
            }

            @Override
            public void onFailure(Call<Response> call, Throwable t) {
                t.printStackTrace();
            }
        });
0 голосов
/ 25 сентября 2018

Вы можете использовать уникальную модель и обрабатывать оба случая с ней:

public class UserResponseModel{

    private String status;
    private String reason;
    private UserModel user;

    // getter/setter

    boolean isFailure(){
        return status == "failure"
    }
    boolean isSuccess(){
        return status == "success"
    }
}

затем вы можете сделать

UserResponseModel response
if( response.isSuccess() ) // do whatever with response.user
else // do whatever with response.reason
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...