1

我遇到了问题:我一直在创建一个将返回响应的登录过程。如果登录为真,它将给出这样的响应。

{   
    "error": false,   "message": "Logged In Successfully",   
    "user": {
        "username": "administrator",
        "email": "admin@admin.com",
        "first_name": "USER",
        "last_name": "ADMIN"   
    },   
    "menu": [
       {
         "name": "MENU A",
         "module": "menu_a",
         "controller": "",
         "parent_module": "",
         "status": ""
       },
       {
          "name": "MENU B",
          "module": "menu_b",
          "controller": " ",
          "parent_module": "",
          "status": ""
       }   
    ],   
    "privilege": [
       {
           "module": "menu_a"
       },
       {
           "module": "menu_b"
       }   
    ] 
}

然后当它为假时,它将返回这样的响应。

{   "error": true,   "message": "Incorrect Login",   "user": {
    "username": "none",
    "email": "none",
    "first_name": "none",
    "last_name": "none",
    "company": "none",
    "phone": "none",
    "gender": "none",
    "place_of_birth": "none",
    "date_of_birth": "none",
    "religion": "none",
    "photo": "none"   },   "menu": "none",   "privilege": "none" }

这是我的代码:

public interface AppDataSource {   

     Single<LoginResponse> attemptLogin(Login login);

     Single<LoginResponse> saveUserData(LoginResponse response);

}

public class AppRemoteDataSource implements AppDataSource {

    private final Retrofit retrofit;

    @Inject
    public AppRemoteDataSource(@NonNull Retrofit retrofit) {
        this.retrofit = retrofit;
    }

    @Override
    public Single<LoginResponse> attemptLogin(Login login) {
        return retrofit.create(OmrService.class).loginUser(login);
    }

    @Override
    public Single<Boolean> checkLogin() {
        throw new UnsupportedOperationException();
    }
}

public class AppLocalDataSource implements AppDataSource {

    @NonNull
    private final SharedPreferences sharedPreferences;

    @NonNull
    private final Realm realm;

    @Inject
    public AppLocalDataSource(@NonNull SharedPreferences sharedPreferences, @NonNull Realm realm) {
        this.sharedPreferences = sharedPreferences;
        this.realm = realm;
    }
    @Override
    public Single<Boolean> checkLogin() {
       return Single.create(s -> {
           Boolean stsLogin = sharedPreferences.getBoolean("IS_USER_LOGIN", >false);
           s.onSuccess(stsLogin);
       });
    }
    @Override
    public Single<LoginResponse> saveUserData(LoginResponse response) {
       return Single.create(e -> {
           if(!response.isError()) {
               savePreference(response.getUser());
               saveMenuPrivilege(response.getMenu(), >response.getPrivilege());
           }
           e.onSuccess(response);
       });
    }

}

public class AppRepository implements AppDataSource {

    @NonNull
    private final AppDataSource localDataSource;

    @NonNull
    private final AppDataSource remoteDataSource;

    @Inject
    public AppRepository(@NonNull @Local AppDataSource localDataSource,
                         @NonNull @Remote AppDataSource remoteDataSource) {
        this.localDataSource = localDataSource;
        this.remoteDataSource = remoteDataSource;
    }

    @Override
    public Single<LoginResponse> attemptLogin(Login login) {
        return remoteDataSource.attemptLogin(login)
                .compose(RxUtils.applySingleSchedulers())
                .flatMap(localDataSource::saveUserData);
    }

    @Override
    public Single<Boolean> checkLogin() {
        return localDataSource.checkLogin();
    }

}

public class LoginPresenter implements LoginContract.Presenter {


    private LoginContract.View view;

    private CompositeDisposable compositeDisposable = new CompositeDisposable();

    private AppRepository repository;


    @Inject
    public LoginPresenter(AppRepository repository, LoginContract.View view) {
        this.repository = repository;
        this.view = view;

    }

    private void attemptLogin(Login login) {
        view.showProgressIndicator(true);
        compositeDisposable.add(repository.attemptLogin(login)
                .subscribe(
                        response -> {
                            if(response.isError()) {
                                Log.d("CHECK RESPONSE ", response.getMessage());
                                view.makeSnack(response.getMessage().toString().replace("<p>","").replace("</p>",""));
                            } else {
                                view.showProgressIndicator(false);
                                view.startMainActivity();
                            }
                        } , e -> {
                            Log.d("CHECK RESPONSE ERROR", e.getMessage());
                            view.makeSnack(e.getMessage().toString());
                            view.showProgressIndicator(false);
                        }
                ));
    }
}

问题是,当我测试假用户名时,Toast 中显示的响应不是“登录错误”,而是“com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 268 路径 $.menu"

我知道登录为假时菜单和权限为空。但是我如何才能捕捉到响应消息“登录错误”?,我需要更改代码的任何部分吗?

提前致谢

4

1 回答 1

1

问题是你的privilege钥匙。

成功时它是一个数组:"privilege": [ { "module": "menu_a" }, { "module": "menu_b" } ]

失败时它是一个字符串:“privilege”:“none”

使其工作的一个简单方法是更改"none"​​为[]

问题出在您的 JSON 反序列化器(GSON?)中,它显然不能以相同的方式同时表示字符串和数组。

因此,如果您无法更改服务器响应,您很可能需要创建一个可以为您进行转换的自定义反序列化器。如何做到这一点取决于用于将 JSON 转换为 Java 的内容。

于 2017-11-17T08:36:10.993 回答