Маппинг JSON ответа от сервера в Java Objects в Android c помощью GSON

Определения:
JSON (англ. JavaScript Object Notation) — текстовый формат обмена данными, основанный на JavaScript. Как и многие другие текстовые форматы, JSON легко читается людьми. Формат JSON был разработан Дугласом Крокфордом.
Gson (так же известная как Google Gson) это библиотека Java библиотека для сериализации и десериализации Java объектов в(и из) JSON.

Разберемся на примере:
У нас есть некий web-сервер с сайтом (https://example.com/), например это будет сайт на 1С Битрикс с установленным интернет-магазином. Нам нужно получить товары с этого сайта и как-то вывести их у себя в приложении. Допустим, что у вас есть бэкендер, который отдает каталог в JSON формате.

Первым делом мы должны выполнить GET или POST запрос к странице, которая отдаст нам этот JSON ответ.
Для этого я использую библиотеку okHTTP3 (https://github.com/square/okhttp). Чтобы добавить библиотеку в наш проект, заходим в build.gradle и добавляем в секцию «dependencies» стоку:
'com.squareup.okhttp3:okhttp:3.8.1'  //3.8.1 версия библиотеки на момент написания статьи.

и сразу добавим библиотеку GSON
compile 'com.google.code.gson:gson:2.8.0'  //2.8.0 версия библиотеки на момент написания статьи.

Выполняем синхронизацию Gradle.

Переходим в класс, в котором будем делать запрос к серверу, для простоты мы будем делать это в MainActivity метод onCreate.

OkHttpClient client = new OkHttpClient.Builder().build(); //Создаем клиента, у которого есть несколько параметров, один из полезнейших это кеш.
Request request = new Request.Builder()
                .url("http://example.com/api_mobile/product/category.php?iblock_id=5§ion_id="+0)
                .build();    //Строим запрос, передавая серверу необходимые параметры, в данном случае простой GET запрос. 
//Далее собственно выполняем сам запрос 
client.newCall(request).enqueue(new Callback() {
                @Override
            public void onFailure(Call call, IOException e) {
                        Log.e("myAPP", e.getMessage());  //Выводим в лог текст ошибки.
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()){   //Проверяем успешен ли наш запрос
                    try {
                        category = gson.fromJson(response.body().charStream(), CategoryResponce.class);  // Маппим ответ от сервера в класс экземпляр класса CategoryResponce
                    } catch (Exception e) {
                        e.printStackTrace();   //Выводим ошибку, будет Exeption если что-то не верно маппится, при такой конструкции не приведет к  падению всего приложения.
                    }

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            updateUI();
                        }
                    });
                }
            }

        });


Вообще okhttp позволяет выполнить запрос двумя методами: execute() и enqueue().
Я использую enqueue(), т.к. по настоятельным рекомендациям Google мы все внешние запросы должны отделять от UI потока. И тут у нас два пути развития:
  1. использовать execute(), но его нужно будет отделять от UI потока путем AsyncTask'a
  2. использовать enqueue() c callbak'ом
Второй вариант предпочтительнее, т.к. делает код более прямолинейным и соответственно более читабельным.

Для примера привожу код с использованием AsyncTask:
public class getCategoryTask extends AsyncTask<Void, Void, Void> {
        private Context mContext;
        private String jsonResult;
        private final OkHttpClient client = new OkHttpClient();
        private final Gson gson = new Gson();
        private   Response response;
        private CategoryResponce category;

        public getCategoryTask(Context cont) {
            mContext = cont;
        }

        @Override
        protected Void doInBackground(Void... params) {
            Request request = new Request.Builder()
                    .url(http://example.com/api_mobile/product/category.php?iblock_id=5§ion_id="+0)
                    .build();
            try {
           response = client.newCall(request).execute();
           category = gson.fromJson(response.body().charStream(), CategoryResponce.class);
            } catch (IOException e) {
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
        }
    }
 }

//Запуск AsyncTask'а
 getCategoryTask getCategory = new getCategoryTask(this);
 getCategory.execute();


Так http запросом разобрались. Теперь подробнее о GSON.
Сам маппинг происходит в строке: category = gson.fromJson(response.body().charStream(), CategoryResponce.class);
где нас интересует класс CategoryResponce.
В моем случае это:
public class CategoryResponce {
    @SerializedName("ID")
    @Expose
    private String iD;
    @SerializedName("TIMESTAMP_X")
    @Expose
    private String tIMESTAMPX;
    @SerializedName("MODIFIED_BY")
    @Expose
    private String mODIFIEDBY;
    @SerializedName("DATE_CREATE")
    @Expose
    private String dATECREATE;
    @SerializedName("CREATED_BY")
    @Expose
    private String cREATEDBY;
    @SerializedName("IBLOCK_ID")
    @Expose
    private String iBLOCKID;
    @SerializedName("IBLOCK_SECTION_ID")
    @Expose
    private Object iBLOCKSECTIONID;
    @SerializedName("ACTIVE")
    @Expose
    private String aCTIVE;
    @SerializedName("GLOBAL_ACTIVE")
    @Expose
    private String gLOBALACTIVE;
    @SerializedName("SORT")
//......
//Getters & Setters 
//....

Весь код приводить не буду, так как он очень большой. Каждое свойство класса берется из JSON ответа, для этого нужно три строки кода:
@SerializedName(«ID») — указываем ключ для сериализации/десериализации JSON
@Expose — нотация указывающая, что следом идет свойство куда «поместить» полученное значение
private String iD; — собственно само свойство.

Писать данные классы вручную не обязательно, я использую www.jsonschema2pojo.org/.
Все просто копируем json ответ от сервера и вставляем его на сайте, выбираем нужные параметры и сайт нам создаст нужную иерархию классов. Быстро и качественно.
  • 0
  • 26 июля 2017, 10:36
  • admin

Комментарии (0)

RSS свернуть / развернуть
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.
Яндекс.Метрика