改造 2:从响应正文中获取 JSON
Posted
技术标签:
【中文标题】改造 2:从响应正文中获取 JSON【英文标题】:Retrofit 2: Get JSON from Response body 【发布时间】:2017-04-19 19:25:36 【问题描述】:我想使用改造 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)
);
我是改造 2 的新手,使用上面的代码,它总是让我的应用程序崩溃,因为 response.body().toString()
返回 null。
请指导我如何获取该 json 字符串,以便我可以将其转换为 JsonObject。
【问题讨论】:
看看***.com/questions/21398598/… 您只能访问 response.body.string() 一次,之后它将返回 null。 response.body().toString() 我已经改成 try String result = response.body().string(); catch(异常 e) e.printStackTrace(); 为我工作! 【参考方案1】:使用此 link 将您的 JSON 转换为 POJO,并使用下图中选择的选项
你会得到一个 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 格式的响应,请从 Retrofit 中删除 addConverterFactory(GsonConverterFactory.create())
。如果没有,则使用上述解决方案
【讨论】:
我一直在寻找的最接近的解决方案,但新版本向我们提供 public void onResponse(retrofit.Response如果您想获得 JSON 格式的完整响应,请尝试以下操作:
我尝试了一种新方法,无需创建任何模型类即可从服务器获取 JSON 格式的完整响应。 我没有使用任何模型类从服务器获取数据,因为我不知道我会得到什么响应,或者它可能会根据要求而改变。
这是 JSON 响应:
"contacts": [
"id": "c200",
"name": "sunil",
"email": "email@gmail.com",
"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": "johnny_depp@gmail.com",
"address": "xx-xx-xxxx,x - street, x - country",
"gender" : "male",
"phone":
"mobile": "+91 0000000000",
"home": "00 000000",
"office": "00 000000"
,
.
.
.
]
在您的 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);
在您调用它的主要活动中
ApiInterface apiService =
ApiClient.getClient().create(ApiInterface.class);
Call call = apiService.getmovies("a@gmail.com","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
);
之后就可以正常使用JSON对象和JSON数组获取参数了
输出
【讨论】:
【参考方案3】:用它来获取字符串
String res = response.body().string();
而不是
String res = response.body().toString();
在将 responsebody 转换为字符串之前始终检查 null
if(response.body() != null)
//do your stuff
【讨论】:
这不起作用...响应正文是一次性值,只能使用一次因此在调试时,检查员会在“幕后”进行调用,并且正文是总是空的。response.body()
已经为您的改造调用构建了一个 POJO,它不一定有 string()
方法。【参考方案4】:
你可以这样使用它。
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();
【讨论】:
【参考方案5】:我发现其他答案的组合有效:
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://***.com/a/33286112/860488
【讨论】:
【参考方案6】:为改造2添加依赖项
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
【讨论】:
【参考方案7】:更好的方法是让 Retrofit 从 json 中为你生成 POJO(使用 gson
)。首先是在创建Retrofit
实例时添加.addConverterFactory(GsonConverterFactory.create())
。例如,如果您有一个与您的 json 对应的 User
java 类(如下所示),那么您的改造 api 可以返回 Call<User>
class User
private String id;
private String Username;
private String Level;
...
【讨论】:
很抱歉不同意,但 Retrofit 不会从 json 生成 POJO,而只会生成基于先前声明的 POJO 的对象。 是的,这就是我的意思......“生成 POJO 实例”我同意会更清楚 请注意:您需要将 'com.squareup.retrofit2:converter-gson:try
JSONObject jsonObject = new JSONObject(response.body().string());
System.out.println(jsonObject);
catch (JSONException | IOException e )
e.printStackTrace();
【讨论】:
【参考方案9】:所以,这是交易:
制作时
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Config.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
您在此处传递 GsonConverterFactory.create()。如果你这样做,Gson 会自动将你得到的 json 对象转换为你的对象<ResponseBody>
。在这里你可以传递所有其他的转换器如Jackson等...
【讨论】:
【参考方案10】:如果您不知道 API 的响应可能是什么。按照步骤将 responsebody 响应值转换为字节并以 String 格式打印您可以在控制台中打印出整个响应。
然后你就可以轻松地将字符串转换为 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))
)
【讨论】:
【参考方案11】:如果您需要 json 字符串响应,您可以使用下面给出的代码更改您的界面..
@FormUrlEncoded
@POST("/api/level")
Call<JsonObject> checkLevel(@Field("id") int id);
并使用此功能进行改造
Call<JsonObject> call = api.checkLevel(1);
call.enqueue(new Callback<JsonObject>()
@Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response)
Log.d("res", response.body().toString());
@Override
public void onFailure(Call<JsonObject> call, Throwable t)
Log.d("error",t.getMessage());
);
【讨论】:
【参考方案12】:你可以像下面这样的用户...
API接口
public interface Api
@POST("app-api/user-login")
Call<RegistrationResponseModel> doLogin( @Body RegistrationModel userModel);
ApiService
public class ApiService
Gson gson = new GsonBuilder()
.setLenient()
.create();
public static final String BASE_URL = "your api url";
Api api = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build().create(Api.class);
public Call<RegistrationResponseModel> doLogin(RegistrationModel model)
return api.doLogin(model);
请求模型
public class RegistrationModel
String fullName="";
String eamil="";
String phone="";
String password="";
int id = 0;
//getter or setter
响应模型
public class RegistrationResponseModel
private String outMessage;
private String outCode;
//getter setter
通话活动
private void doLogin()
ApiService apiService = new ApiService();
RegistrationModel model = new RegistrationModel();
model.setPhone("0192144444");
model.setPassword("123");
model.setId(3);
Call<RegistrationResponseModel> call = apiService.doLogin(model);
call.enqueue(new Callback<RegistrationResponseModel>()
@Override
public void onResponse(Call<RegistrationResponseModel> call, Response<RegistrationResponseModel> response)
@Override
public void onFailure(Call<RegistrationResponseModel> call, Throwable t)
);
别忘了添加下面的库
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
添加工具:在应用程序下的清单文件中替换。清单文件看起来像..
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="your package">
<uses-permission android:name="android.permission.INTERNET" />
<application
......
tools:replace="android:icon" >
</application>
</manifest>
好好享受吧……
【讨论】:
【参考方案13】:您可以从原始对象获取 json 响应 正如你所做的那样,你从 api 获得 ResponseBody
Call<ResponseBody>
在内部回调中,您可以获得您的 json 响应
json = response.raw().toString();
【讨论】:
【参考方案14】:使用这个
response.body().get(0).getUsername().toString();
【讨论】:
以上是关于改造 2:从响应正文中获取 JSON的主要内容,如果未能解决你的问题,请参考以下文章