web-dev-qa-db-ja.com

レトロフィット2:応答本文からJSONを取得する

レトロフィット2を使用してAPIからストリングjsonを取得したいのですが、レトロフィット1を使用してこのjsonを取得しても問題ありませんが、レトロフィット2を使用するとnullが返されます。

これは私のJSONのようです

{"id":1,"Username":"admin","Level":"Administrator"}

これは私のAPIです

@FormUrlEncoded
@POST("/api/level")
Call<ResponseBody> checkLevel(@Field("id") int id);

これは私のコードがどのように見えるかです

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Config.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        Api api = retrofit.create(Api.class);
        Call<ResponseBody> call = api.checkLevel(1);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                JsonObject post = new JsonObject().get(response.body().toString()).getAsJsonObject();
                    if (post.get("Level").getAsString().contains("Administrator")) {

                    }
            }

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

私はretrofit 2を初めて使用し、上記のコードを使用すると、response.body().toString()がnullを返すため、常にアプリがクラッシュします。

Json文字列を取得してJsonObjectに変換できるようにする方法を教えてください。

46
Dirus

この リンク を使用して、下の画像で選択されている選択オプションを使用してJSONをPOJOに変換します

enter image description here

次のような応答のPOJOクラスを取得します

public class Result {

    @SerializedName("id")
    @Expose
    private Integer id;
    @SerializedName("Username")
    @Expose
    private String username;
    @SerializedName("Level")
    @Expose
    private String level;

    /**
    * 
    * @return
    * The id
    */
    public Integer getId() {
        return id;
    }

    /**
    * 
    * @param id
    * The id
    */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
    * 
    * @return
    * The username
    */
    public String getUsername() {
        return username;
    }

    /**
    * 
    * @param username
    * The Username
    */
    public void setUsername(String username) {
        this.username = username;
    }

    /**
    * 
    * @return
    * The level
    */
    public String getLevel() {
        return level;
    }

    /**
    * 
    * @param level
    * The Level
    */
    public void setLevel(String level) {
        this.level = level;
    }

}

そして次のようなインターフェースを使用します:

@FormUrlEncoded
@POST("/api/level")
Call<Result> checkLevel(@Field("id") int id);

そして次のように呼び出します:

Call<Result> call = api.checkLevel(1);
call.enqueue(new Callback<Result>() {
    @Override
    public void onResponse(Call<Result> call, Response<Result> response) { 
     if(response.isSuccessful()){
        response.body(); // have your all data
        int id =response.body().getId();
        String userName = response.body().getUsername();
        String level = response.body().getLevel();
        }else   Toast.makeText(context,response.errorBody().string(),Toast.LENGTH_SHORT).show(); // this will tell you why your api doesnt work most of time

    }

    @Override
    public void onFailure(Call<Result> call, Throwable t) {
     Toast.makeText(context,t.toString(),Toast.LENGTH_SHORT).show(); // ALL NETWORK ERROR HERE

    }
});

gradleで依存関係を使用する

compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.+'

注:エラーは、JSONをPOJOに変更したために発生します(後付けでaddConverterFactory(GsonConverterFactory.create())を使用)。 JSONで応答する場合は、addConverterFactory(GsonConverterFactory.create())をRetrofitから削除します。そうでない場合は、上記のソリューションを使用してください

43
sushildlh

JSON形式で全体の応答を取得する場合は、これを試してください:

モデルクラスを作成せずに、JSON形式でサーバーから応答全体を取得する新しい方法を試しました。 サーバーからデータを取得するためにモデルクラスを使用していません、どの応答を取得するかわからないか、要件に応じて変更される可能性があります。

これはJSONレスポンスです:

{"contacts": [
    {
        "id": "c200",
        "name": "sunil",
        "email": "[email protected]",
        "address": "xx-xx-xxxx,x - street, x - country",
        "gender" : "male",
        "phone": {
            "mobile": "+91 0000000000",
            "home": "00 000000",
            "office": "00 000000"
        }
    },
    {
        "id": "c201",
        "name": "Johnny Depp",
        "email": "[email protected]",
        "address": "xx-xx-xxxx,x - street, x - country",
        "gender" : "male",
        "phone": {
            "mobile": "+91 0000000000",
            "home": "00 000000",
            "office": "00 000000"
        }
    },
    .
    .
    .
]}
  1. APIインターフェースでパラメーターを変更します

    public interface ApiInterface {
    @POST("/index.php/User/login")//your api link 
    @FormUrlEncoded
    Call<Object> getmovies(@Field("user_email_address") String title,
                    @Field("user_password") String body);
    }
    
  2. これを呼び出しているメインアクティビティで

    ApiInterface apiService =
            ApiClient.getClient().create(ApiInterface.class);
    
    Call call = apiService.getmovies("[email protected]","123456");
    call.enqueue(new Callback() {
        @Override
        public void onResponse(Call call, Response response) {
            Log.e("TAG", "response 33: "+new Gson().toJson(response.body()) );
        }
    
        @Override
        public void onFailure(Call call, Throwable t) {
            Log.e("TAG", "onFailure: "+t.toString() );
            // Log error here since request failed
        }
    });
    
  3. その後、通常はJSONオブジェクトとJSON配列を使用してパラメーターを取得できます

出力 enter image description here

33
Sunil

これを使用して文字列を取得します

String res = response.body().string();

の代わりに

String res = response.body().toString();

responsebodyを文字列に変換する前に常にnullのチェックを保持します

if(response.body() != null){
     //do your stuff   
}

retrofit2の依存関係を追加します

compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

ベースURLのクラスを作成します

public class ApiClient     
{
public static final String BASE_URL = "base_url";

private static Retrofit retrofit = null;

public static Retrofit getClient() {
    if (retrofit==null) {
        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }
    return retrofit;
}

}

その後、クラスモデルを作成して値を取得します

public class ApprovalModel {

@SerializedName("key_parameter")
private String approvalName;
public String getApprovalName() {
    return approvalName;
}
}

インターフェイスクラスを作成する

public interface ApiInterface { 
@GET("append_url")
Call<CompanyDetailsResponse> getCompanyDetails();
}

その後メインクラスで

 if(Connectivity.isConnected(mContext)){
            final ProgressDialog mProgressDialog = new ProgressDialog(mContext);
            mProgressDialog.setIndeterminate(true);
            mProgressDialog.setMessage("Loading...");
            mProgressDialog.show();

            ApiInterface apiService =
                    ApiClient.getClient().create(ApiInterface.class);

            Call<CompanyDetailsResponse> call = apiService.getCompanyDetails();
            call.enqueue(new Callback<CompanyDetailsResponse>() {
                @Override
                public void onResponse(Call<CompanyDetailsResponse>call, Response<CompanyDetailsResponse> response) {
                    mProgressDialog.dismiss();
                    if(response!=null && response.isSuccessful()) {
                        List<CompanyDetails> companyList = response.body().getCompanyDetailsList();

                        if (companyList != null&&companyList.size()>0) {
                            for (int i = 0; i < companyList.size(); i++) {
                                Log.d(TAG, "" + companyList.get(i));
                            }
                         //get values
                        }else{
                            //show alert not get value
                        }
                    }else{
                        //show error message

                    }
                }

                @Override
                public void onFailure(Call<CompanyDetailsResponse>call, Throwable t) {
                    // Log error here since request failed
                    Log.e(TAG, t.toString());
                    mProgressDialog.dismiss();
                }
            });
        }else{
            //network error alert box

        }
4
Mahesh Pandit

このように使用できます。

 public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
            if (response.isSuccessful()) {
                try {
                    JSONObject jsonObject = new JSONObject(new Gson().toJson(response.body()));
                    msg = jsonObject.getString("msg");
                    status = jsonObject.getBoolean("status");

                    msg = jsonObject.getString("msg");
                    status = jsonObject.getBoolean("status");
                } catch (JSONException e) {
                    e.printStackTrace();
                }

                Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
                Log.e("cvbnop",response.body().toString());
            } else {
                Toast.makeText(MainActivity.this, "Some error occurred...", Toast.LENGTH_LONG).show();
            }
        }
3
Krishna

より良いアプローチは、jsonからRetrofitにPOJOを生成させることです(gsonを使用)。まず、Retrofitインスタンスを作成するときに.addConverterFactory(GsonConverterFactory.create())を追加します。たとえば、jsonに対応するUser Javaクラス(以下に示すような)がある場合、レトロフィットAPIはCall<User>を返すことができます

class User {
    private String id;
    private String Username;
    private String Level;
    ...
}    
2
John O'Reilly

私は他の答えの組み合わせが機能することを発見しました:

interface ApiInterface {
    @GET("/someurl")
    Call<ResponseBody> getdata()
}

apiService.getdata().enqueue(object : Callback {
    override fun onResponse(call: Call, response: Response) {
        val rawJsonString = response.body()?.string()
    }
})

重要な部分は、応答タイプがResponseBodyであり、response.body()?.string()を使用して生の文字列を取得することです。

https://stackoverflow.com/a/33286112/860488

1

APIからの応答が何であるかわからない場合。手順に従って、responsebodyの応答値をバイトに変換し、文字列形式で出力します。応答全体をコンソールに出力できます。

その後、文字列をJSONObjectに簡単に変換できます。

      apiService.getFeeds(headerMap, map).enqueue(object : Callback, retrofit2.Callback<ResponseBody> {
            override fun onFailure(call: Call<ResponseBody>?, t: Throwable?) {
            }

            override fun onResponse(call: Call<ResponseBody>?, response: Response<ResponseBody>?) {
                val bytes = (response!!.body()!!.bytes())
                Log.d("Retrofit Success : ", ""+ String(bytes))
            }
        })
1
Sackurise

だから、ここに取引があります:

作るとき

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Config.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

ここでGsonConverterFactory.create()を渡します。このようにすると、Gsonはオブジェクト<ResponseBody>に応答して取得したjsonオブジェクトを自動的に変換します。ここでは、ジャクソンなどの他のすべてのコンバーターを渡すことができます...

1
Vulovic Vukasin