如何在改造中处理dynamicJSON?
我正在使用高效的networking库改造,但我无法处理dynamicJSON,其中包含单个前缀responseMessage
随机更改object
,相同的前缀( responseMessage
)在某些情况下(dynamic)更改为string。
Json格式responseMessage的对象:
{ "applicationType":"1", "responseMessage":{ "surname":"Jhon", "forename":" taylor", "dob":"17081990", "refNo":"3394909238490F", "result":"Received" } }
responseMessage
Json格式dynamic更改为stringtypes:
{ "applicationType":"4", "responseMessage":"Success" }
对我来说这个问题是因为改造已经内置JSON
parsing,我们必须为每个请求分配单个POJO! 但不幸的是REST-API是用dynamic的JSON
响应构build的,在成功(…)和失败(…)方法中,前缀将随机变为string和对象。
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(); } }); }
POJO:
public class TrackerRefResponse { private String applicationType; private String responseMessage; //String type //private ResponseMessage responseMessage; //Object of type ResponseMessage //Setters and Getters }
在上面的代码中,POJO TrackerRefResponse.java前缀responseMessage被设置为responseMessagetypes的string或对象,所以我们可以用同名的javavariables创buildPOJO(java基础知识:)),所以我正在寻找同样的解决scheme,用于dynamicJSON
的Retrofit 。 我知道在具有asynchronous任务的普通http客户机中这是非常容易的工作,但这不是REST-Api JSON
parsing中的最佳做法! 看性能基准总是排气或改造是最好的select,但我失败处理dynamicJSON
!
我知道可能的解决scheme
-
使用旧的asyc任务与http客户端parsing。 🙁
-
尝试说服RESTapi后端开发者。
-
创build自定义的Retrofit客户端:)
晚会,但你可以使用一个转换器。
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);
然后你使用一个实现改造的转换器的静态类:
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(); } }
我已经写了这个样本转换器,所以它返回的Json响应无论是作为string,对象,JsonObject或地图<string,对象>。 很明显,并不是所有的退货types都适用于每个Json,并且还有一定的改进空间。 但它演示了如何使用转换器将几乎任何响应转换为dynamicJson。
RestClient.java
import retrofit.client.Response; public interface RestClient { @GET("/api/foo") Response getYourJson(); }
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); }
你必须实现“checkResponseMessage”方法。
你的任何可能的解决scheme将工作。 你也可以做的是发送Retrofit api接口返回types到响应。 通过这个响应,你可以得到一个正文Inputstream
,你可以将它转换成一个JSON对象,然后按你认为合适的方式读取。
看看: http : //square.github.io/retrofit/#api-declaration – 在RESPONSE OBJECT TYPE下
更新
改造2现在已经出来,并且对文档和库进行了一些更改。
看看http://square.github.io/retrofit/#restadapter-configuration里面有可以使用的request和response body对象。
被接受的答案似乎过于复杂,我这样解决:
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()); } });
这只是一个例子,试图告诉你如何使用不同的模型。
variablesisEmail
只是您的条件使用适当的模型的布尔值。
我知道我对这个晚会非常迟。 我有一个类似的问题,只是解决这个问题:
public class TrackerRefResponse { private String applicationType; // Changed to Object. Works fine with String and array responses. private Object responseMessage; }
我从字面上改为inputObject。 我select了这种方法,因为响应中只有一个字段是dynamic的(对我来说,我的回答更为复杂),所以使用转换器会使生活困难。 使用Gson来从那里使用对象,取决于它是一个string还是数组值。
希望这可以帮助别人寻找一个简单的答案:)。
如果无法更改后端API,我会考虑以下变体(如果使用Gson转换JSON)。
-
我们可以使用Gson types适配器为
ResponseMessage
types创build一个自定义的适配器,它dynamic地决定如何parsing开启的JSON(使用类似if (reader.peek() == JsonToken.STRING)
)。 -
将一些描述响应types的元信息放入一个HTTP头中,并用它来确定必须将什么types的信息input到Gson实例中。
改变你的pojo像这样
public class TrackerRefResponse { private String applicationType; private Object responseMessage; public Object getResponseMessage() { return responseMessage; } public void setResponseMessage(Object responseMessage) { this.responseMessage = responseMessage; } }
并像这样改变改造的onResponse
@Override public void onResponse(Response<TrackerRefResponse > response) { if (response.isSuccess()) { if (response.getResponseMessage() instanceof List<TrackerRefResponse>) { handleListResponse(); } else if (response.getResponseMessage() instanceof String) { handleStringResponse(); } } }
除了你所说的 –
使用callback然后,您可以使用常规的get方法来检索字段。 有关更多信息,请通过gson的javadoc。
http://google-gson.googlecode.com/svn/tags/1.2.3/docs/javadocs/com/google/gson/JsonObject.html