如何在改造中处理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" } 

对我来说这个问题是因为改造已经内置JSONparsing,我们必须为每个请求分配单个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 JSONparsing中的最佳做法! 看性能基准总是排气或改造是最好的select,但我失败处理dynamicJSON

我知道可能的解决scheme

  1. 使用旧的asyc任务与http客户端parsing。 🙁

  2. 尝试说服RESTapi后端开发者。

  3. 创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)。

  1. 我们可以使用Gson types适配器为ResponseMessagetypes创build一个自定义的适配器,它dynamic地决定如何parsing开启的JSON(使用类似if (reader.peek() == JsonToken.STRING) )。

  2. 将一些描述响应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