Как обращаться с Dynamic JSON в Модернизации?

Я использую эффективную сетевую библиотечную модернизацию, но мне не удалось обработать Dynamic JSON, который содержит одиночный префикс responseMessage который случайным образом изменяется на object , тот же префикс ( responseMessage ) в некоторых случаях (динамически) изменяется на String.

Формат Json Объект responseMessage:

 { "applicationType":"1", "responseMessage":{ "surname":"Jhon", "forename":" taylor", "dob":"17081990", "refNo":"3394909238490F", "result":"Received" } } 

Формат responseMessage Json динамически изменяется на строку типа:

  { "applicationType":"4", "responseMessage":"Success" } 

Проблема для меня в том, что у retrofit есть встроенный синтаксический анализ 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(); } }); } 

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 задан как строка или объект типа responseMessage, поэтому мы можем создать POJO с переменной ref с тем же именем (основы java :)), поэтому я ищу такое же решение для динамического JSON в Retrofit , Я знаю, что это очень легкая работа в обычных http-клиентах с асинхронной задачей, но это не самая лучшая практика в анализе REST-Api JSON ! Глядя на производительность Benchmarks всегда Volley или Retrofit – лучший выбор, но я не справился с динамическим JSON !

Возможное решение, которое я знаю

  1. Используйте старую задачу asyc с обработкой http-клиента. 🙁

  2. Попробуйте убедить разработчика RESTapi.

  3. Создать пользовательский клиент для переоснащения клиента 🙂

Solutions Collecting From Web of "Как обращаться с Dynamic JSON в Модернизации?"

Поздно к вечеринке, но вы можете использовать конвертер.

 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, Object, JsonObject или Map <String, Object>. Очевидно, что не все типы возвратов будут работать для каждого Json, и есть уверенность в возможности для улучшения. Но он демонстрирует, как использовать конвертер для преобразования почти любого ответа на динамический Json.

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.

Любое из ваших возможных решений будет работать. То, что вы также можете сделать, это отправить возвращаемый тип интерфейса Apo Retrofit в ответ. С этим ответом вы получаете тело Inputstream которое вы можете преобразовать в объект JSON и читать по своему усмотрению.

Посмотрите: http://square.github.io/retrofit/#api-declaration – в соответствии с ТИП ОБЪЕКТА РЕАГИРОВАНИЯ

обновленный

В настоящее время 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()); } }); 

Это просто пример попытки показать вам, как вы можете использовать другую модель.

Переменная isEmail является просто логической для вашего условия, чтобы использовать соответствующую модель.

Я знаю, что очень опаздываю на вечеринку. У меня была аналогичная проблема, и я просто решил ее так:

 public class TrackerRefResponse { private String applicationType; // Changed to Object. Works fine with String and array responses. private Object responseMessage; } 

Я буквально просто изменил тип на Object. Я выбрал этот подход, потому что только одно поле в ответе было динамическим (для меня мой ответ был более сложным), поэтому использование конвертера затруднило бы жизнь. Использовал Gson для работы с объектом оттуда, в зависимости от того, было ли это значение String или Array.

Надеюсь, это поможет кому-то найти простой ответ :).

Если было невозможно изменить API-интерфейс, я бы рассмотрел следующие варианты (если Gson используется для преобразования JSON).

  1. Мы можем использовать адаптеры типа Gson для создания настраиваемого адаптера для типа ResponseMessage который динамически решает, как разбирать встроенный JSON (используя что-то вроде if (reader.peek() == JsonToken.STRING) ).

  2. Поместите некоторую метаинформацию, описывающую тип ответа, в HTTP-заголовок и используйте его для определения того, какая информация типа должна быть подана в экземпляр Gson.

В дополнение к тому, что вы сказали –

Использовать обратный вызов. Затем вы можете получать поля с помощью обычного метода get. Для получения дополнительной информации перейдите к javadoc gson.

http://google-gson.googlecode.com/svn/tags/1.2.3/docs/javadocs/com/google/gson/JsonObject.html