LOG*_*TAG 75 android json gson retrofit
我正在使用高效的网络库改造,但是我无法处理包含单个前缀的Dynamic JSON, responseMessage
后者object
随机responseMessage
变化,在某些情况下(动态),相同的prefix()会更改为String.
Json格式responseMessage的对象:
{
"applicationType":"1",
"responseMessage":{
"surname":"Jhon",
"forename":" taylor",
"dob":"17081990",
"refNo":"3394909238490F",
"result":"Received"
}
}
Run Code Online (Sandbox Code Playgroud)
responseMessage
Json格式动态更改为类型字符串:
{
"applicationType":"4",
"responseMessage":"Success"
}
Run Code Online (Sandbox Code Playgroud)
对我来说问题是因为改造有内置的JSON
解析我们必须为每个请求分配单个POJO!但遗憾的是,REST-API是使用动态JSON
响应构建的,前缀将在成功(...)和失败(...)方法中随机更改为字符串到对象!
void doTrackRef(Map<String, String> paramsref2) {
RestAdapter restAdapter = new RestAdapter.Builder().setEndpoint("http://192.168.100.44/RestDemo").build();
TrackerRefRequest userref = restAdapter.create(TrackerRefRequest.class);
userref.login(paramsref2,
new Callback<TrackerRefResponse>() {
@Override
public void success(
TrackerRefResponse trackdetailresponse,
Response response) {
Toast.makeText(TrackerActivity.this, "Success",
Toast.LENGTH_SHORT).show();
}
@Override
public void failure(RetrofitError retrofitError) {
Toast.makeText(TrackerActivity.this, "No internet",
Toast.LENGTH_SHORT).show();
}
});
}
Run Code Online (Sandbox Code Playgroud)
POJO:
public class TrackerRefResponse {
private String applicationType;
private String responseMessage; //String type
//private ResponseMessage responseMessage; //Object of type ResponseMessage
//Setters and Getters
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中POJO TrackerRefResponse.java前缀responseMessage设置为responseMessage类型的字符串或对象,因此我们可以创建具有相同名称的ref变量的POJO(java basics :))所以我JSON
在Retrofit中寻找相同的动态解决方案.我知道在具有异步任务的普通http客户端中这是非常容易的工作,但它不是REST-Api JSON
解析中的最佳实践!看看性能基准总是Volley或Retrofit是最好的选择,但我失败了处理动态JSON
!
我知道可能的解决方案
使用旧的asyc任务与http客户端解析.:(
试着说服RESTapi后端开发人员.
创建自定义Retrofit客户端:)
Oli*_*ler 38
晚到派对,但你可以使用转换器.
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://graph.facebook.com")
.setConverter(new DynamicJsonConverter()) // set your static class as converter here
.build();
api = restAdapter.create(FacebookApi.class);
Run Code Online (Sandbox Code Playgroud)
然后你使用一个静态类来实现改造的转换器:
static class DynamicJsonConverter implements Converter {
@Override public Object fromBody(TypedInput typedInput, Type type) throws ConversionException {
try {
InputStream in = typedInput.in(); // convert the typedInput to String
String string = fromStream(in);
in.close(); // we are responsible to close the InputStream after use
if (String.class.equals(type)) {
return string;
} else {
return new Gson().fromJson(string, type); // convert to the supplied type, typically Object, JsonObject or Map<String, Object>
}
} catch (Exception e) { // a lot may happen here, whatever happens
throw new ConversionException(e); // wrap it into ConversionException so retrofit can process it
}
}
@Override public TypedOutput toBody(Object object) { // not required
return null;
}
private static String fromStream(InputStream in) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder out = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
out.append("\r\n");
}
return out.toString();
}
}
Run Code Online (Sandbox Code Playgroud)
我编写了这个示例转换器,因此它以String,Object,JsonObject或Map <String,Object>的形式返回Json响应.显然并非所有的返回类型都适用于每个Json,并且肯定有改进的余地.但它演示了如何使用Converter将几乎任何响应转换为动态Json.
Yuk*_*ida 20
RestClient.java
import retrofit.client.Response;
public interface RestClient {
@GET("/api/foo") Response getYourJson();
}
Run Code Online (Sandbox Code Playgroud)
YourClass.java
RestClient restClient;
// create your restClient
Response response = restClient.getYourJson();
Gson gson = new Gson();
String json = response.getBody().toString();
if (checkResponseMessage(json)) {
Pojo1 pojo1 = gson.fromJson(json, Pojo1.class);
} else {
Pojo2 pojo2 = gson.fromJson(json, Pojo2.class);
}
Run Code Online (Sandbox Code Playgroud)
您必须实现"checkResponseMessage"方法.
Nav*_*hna 15
使用gson-converter
以下方法尝试自定义反序列化(Retrofit 2.0的更新答案)
创建三个模型,如下所示
ResponseWrapper此类
public class ResponseWrapper {
@SerializedName("applicationType")
@Expose
private String applicationType;
@SerializedName("responseMessage")
@Expose
private Object responseMessage;
public String getApplicationType() {
return applicationType;
}
public void setApplicationType(String applicationType) {
this.applicationType = applicationType;
}
public Object getResponseMessage() {
return responseMessage;
}
public void setResponseMessage(Object responseMessage) {
this.responseMessage = responseMessage;
}
}
Run Code Online (Sandbox Code Playgroud)
ResponseMessage
public class ResponseMessage extends ResponseWrapper {
@SerializedName("surname")
@Expose
private String surname;
@SerializedName("forename")
@Expose
private String forename;
@SerializedName("dob")
@Expose
private String dob;
@SerializedName("refNo")
@Expose
private String refNo;
@SerializedName("result")
@Expose
private String result;
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getForename() {
return forename;
}
public void setForename(String forename) {
this.forename = forename;
}
public String getDob() {
return dob;
}
public void setDob(String dob) {
this.dob = dob;
}
public String getRefNo() {
return refNo;
}
public void setRefNo(String refNo) {
this.refNo = refNo;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
}
Run Code Online (Sandbox Code Playgroud)
ResponseString
public class ResponseString extends ResponseWrapper {
}
Run Code Online (Sandbox Code Playgroud)
UserResponseDeserializer(自定义反序列化器)
public class UserResponseDeserializer implements JsonDeserializer<ResponseWrapper> {
@Override
public ResponseWrapper deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (((JsonObject) json).get("responseMessage") instanceof JsonObject){
return new Gson().fromJson(json, ResponseMessage.class);
} else {
return new Gson().fromJson(json, ResponseString.class);
}
}
}
Run Code Online (Sandbox Code Playgroud)
改造2.0实施
Gson userDeserializer = new GsonBuilder().setLenient().registerTypeAdapter(ResponseWrapper.class, new UserResponseDeserializer()).create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("base_url")
.addConverterFactory(GsonConverterFactory.create(userDeserializer))
.build();
UserService request = retrofit.create(UserService.class);
Call<ResponseWrapper> call1=request.listAllUsers();
call1.enqueue(new Callback<ResponseWrapper>() {
@Override
public void onResponse(Call<ResponseWrapper> call, Response<ResponseWrapper> response) {
ResponseWrapper responseWrapper=response.body();
Log.i("DYNAMIC RESPONSE", String.valueOf(response.body().getResponseMessage()));
}
@Override
public void onFailure(Call<ResponseWrapper> call, Throwable t) {
}
});
Run Code Online (Sandbox Code Playgroud)
使用的库
编译'com.squareup.retrofit2:改造:2.3.0'
编译'com.squareup.retrofit2:converter-gson:2.3.0'
***** 上一个答案(以上答案更推荐一个)*****
像这样改变你的pojo
public class TrackerRefResponse {
private String applicationType;
private Object responseMessage;
public Object getResponseMessage() {
return responseMessage;
}
public void setResponseMessage(Object responseMessage) {
this.responseMessage = responseMessage;
}
}
Run Code Online (Sandbox Code Playgroud)
并像这样改变改造的onResponse
@Override
public void onResponse(Response<TrackerRefResponse > response) {
if (response.isSuccess()) {
if (response.getResponseMessage() instanceof String)
{
handleStringResponse();
}
else
{
handleObjectResponse();
}
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以查看此帖子,了解有关动态json解析的更多详细信息
Jus*_*ade 10
任何可能的解决方案都可行.你还可以做的是将Retrofit api接口返回类型发送到响应.通过该响应,您将获得一个Inputstream
可以转换为JSON对象并按您认为合适的方式读取的主体.
请看:http://square.github.io/retrofit/#api-declaration - 在RESPONSE OBJECT TYPE下
更新
Retrofit 2现已推出,并对文档和库进行了一些更改.
查看http://square.github.io/retrofit/#restadapter-configuration,可以使用请求和响应正文对象.
接受的答案对我来说似乎过于复杂,我这样解决:
Call<ResponseBody> call = client.request(params);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Response<ResponseBody> response) {
if (response.isSuccess()) {
Gson gson = new Gson();
ResponseBody repsonseBody = response.body().string();
if (isEmail) {
EmailReport reports = gson.fromJson(responseBody, EmailReport.class);
} else{
PhoneReport reports = gson.fromJson(repsonseBody, PhoneReport.class);
}
}
}
@Override
public void onFailure(Throwable t) {
Log.e(LOG_TAG, "message =" + t.getMessage());
}
});
Run Code Online (Sandbox Code Playgroud)
这只是一个示例,试图向您展示如何使用不同的模型.
变量isEmail
只是您使用适当模型的条件的布尔值.
我知道我参加聚会非常晚了.我遇到了类似的问题,就这样解决了:
public class TrackerRefResponse {
private String applicationType;
// Changed to Object. Works fine with String and array responses.
private Object responseMessage;
}
Run Code Online (Sandbox Code Playgroud)
我只是改为键入到Object.我选择这种方法是因为响应中只有一个字段是动态的(对我而言,我的响应更复杂),因此使用转换器会使生活变得困难.使用Gson从那里使用Object,具体取决于它是String还是Array值.
希望这有助于寻找简单答案的人:).
归档时间: |
|
查看次数: |
50977 次 |
最近记录: |