В этом уроке мы с вами более подробно познакомимся с форматом JSON. А потом из этого формата получим наш User объект.
JSON стал общепринятым форматом для обмена данными в клиент-серверных приложения. Он является универсальным форматом для обмена данными.
Представьте, что вам нужно создать систему приложений, в которую входит, сервер, web-клиент, ios-клиент, android-клиент. У всех технологий разные языки,
разные особенности. Поэтому сервер отвечает в формате JSON, а клиенты на своей стороне приводят к нужному формату ответы. Подробнее про JSON формат можно
почитать здесь, но на данном этапе ваших знаний уже вполне хватит.
JSONObject, работа с JSON в java коде
Давайте создадим новый класс в пакете network и назовём его JsonParser для преобразования Json-строк в необходимые нам объекты. Добавим в него один
метод, который назовём getUser(String response):
JsonParser.java
1
2
3
4
5
6
7
8
9
10
package colibri.dev.com.colibritweet.network;importcolibri.dev.com.colibritweet.pojo.User;publicclassJsonParser{public User getUser(String response){returnnull;}}
Мы будем использовать этот метод внутри класса HttpClient, передавая в него ответ от сервера в формате String, возвращая объект User. Давайте
разберём преобразование, рассмотрим структура хранения JSON. В прошлом уроке мы в конце вывели ответ от сервера в log и увидели очень большой объект JSON.
На данном этапе нам необходимы только те поля, которые мы отображаем на экране. Поэтому опустим остальные поля и оставим только те, которые нам нужны:
Видим, что наш JSON полностью повторяет структуру нашего объекта User. Теперь можно приступить к парсингу (преобразованию) данных.
Первое, что необходимо сделать – это создать JSON объект из строки:
JsonParser.java
1
2
3
4
5
6
7
8
9
10
11
package colibri.dev.com.colibritweet.network;importcolibri.dev.com.colibritweet.pojo.User;publicclassJsonParser{public User getUser(String response){
JSONObject userJson =new JSONObject(response);returnnull;}}
Видим, что AndroidStudio подчёркивает эту строку, указывая что надо обработать исключение или добавить его к сигнатуре метода. Можем нажать alt + enter
и увидеть два этих варианта решения проблемы. Добавим исключение к сигнатуре, чтобы обработать исключения в клиентском коде. Для этого выберем вариант Add exception to method signature:
JSONObject представляет из себя структуру типа HashMap (ключ – значение).
Т.е. чтобы получить значения поля id нам необходимо выполнить вызов метода userJson.getLong("id") (получить значение типа long по ключу (названию поля) id). Давайте сделаем тоже самое для каждого поля.
После этого метод будет выглядеть так:
JsonParser.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
publicclassJsonParser{public User getUser(String response)throws JSONException {
JSONObject userJson =new JSONObject(response);long id = userJson.getLong("id");
String name = userJson.getString("name");
String nick = userJson.getString("screen_name");
String location = userJson.getString("location");
String description = userJson.getString("description");
String imageUrl = userJson.getString("profile_image_url");int followersCount = userJson.getInt("followers_count");int followingCount = userJson.getInt("favourites_count");returnnull;}}
Т.е. вот так по названию поля мы можем достать его значение. Нам попался самый простой случай, где наши значения являются примитивными типами. На практике мы
поработаем с массивами элементов и вложенными объектами.
Давайте создадим объект User, передав ему в конструктор все поля, которые мы только что достали из userJson:
publicclassHttpClient{privatestaticfinal String HEADER_AUTHORIZATION ="Authorization";privatestaticfinal String GET ="GET";privatefinal JsonParser jsonParser;publicHttpClient(){
jsonParser =new JsonParser();}public User readUserInfo(long userId)throws IOException, JSONException {
String requestUrl ="https://api.twitter.com/1.1/users/show.json?user_id="+ userId;
URL url =new URL(requestUrl);
HttpURLConnection connection =(HttpURLConnection) url.openConnection();// add auth header to request
String authHeader = getAuthHeader(requestUrl);
connection.setRequestProperty(HEADER_AUTHORIZATION, authHeader);
connection.connect();
InputStream in;int status = connection.getResponseCode();if(status != HttpURLConnection.HTTP_OK){
in = connection.getErrorStream();}else{
in = connection.getInputStream();}
String response = convertStreamToString(in);
User user = jsonParser.getUser(response);return user;}// остальной код ниже не изменился}
Добавили JsonParser как final поле в классе HttpClient и инициализируем его в конструкторе.
После этого добавили строку User user = jsonParser.getUser(response); в конец метода getUserInfo и поменяли возвращаемый тип на User и добавили новое
исключение JSONException в сигнатуру метода. Отлично, теперь изменим код в UserInfoActivity и запустим приложение.
в UserInfoActivity нам нужно изменить метод loadUserInfo:
publicclassUserInfoActivityextends AppCompatActivity {// остальной код выше не изменился
@SuppressLint("StaticFieldLeak")privatevoidloadUserInfo(final Long userId){new AsyncTask<Void, Void, User>(){
@Override
protected User doInBackground(Void... voids){try{return httpClient.readUserInfo(userId);}catch(IOException | JSONException e){
e.printStackTrace();returnnull;}}
@Override
protectedvoidonPostExecute(User user){
displayUserInfo(user);}}.execute();}// остальной код ниже не изменился}
Мы изменили:
Возвращаемый тип Asynctask со String на User.
Добавили в catch блок перехват исключения типа IOException | JSONException.
В onPostExecute мы заменили вызов Log.d() на вызов реального метода отображения displayUserInfo(user).
Давайте запустим наше приложение:
Всё работает! Только видим, что наш ник выводится без символа @. Давайте изменим метод getNick() в классе User. Будем добавлять в него символ @ самостоятельно, т.к. сервер этого не сделал.
User.java
1
2
3
4
5
6
7
8
9
10
publicclassUser{// Остальной код выше не изменилсяpublic String getNick(){return"@"+ nick;}// Остальной код ниже не изменился}
Запустим наше приложение и увидим, что теперь с форматом поля nick всё в порядке:
Сайт использует cookie-файлы для того, чтобы вам было удобнее им пользоваться. Для
продолжения работы с сайтом, вам необходимо принять использование cookie-файлов.
Структура урока:
JSON формат
JSONObject, работа с JSON в java коде
JSON формат
В этом уроке мы с вами более подробно познакомимся с форматом
JSON
. А потом из этого формата получим нашUser
объект.JSON
стал общепринятым форматом для обмена данными в клиент-серверных приложения. Он является универсальным форматом для обмена данными.Представьте, что вам нужно создать систему приложений, в которую входит, сервер,
web
-клиент,ios
-клиент,android
-клиент. У всех технологий разные языки,разные особенности. Поэтому сервер отвечает в формате
JSON
, а клиенты на своей стороне приводят к нужному формату ответы. Подробнее проJSON
формат можнопочитать здесь, но на данном этапе ваших знаний уже вполне хватит.
JSONObject, работа с JSON в java коде
Давайте создадим новый класс в пакете
network
и назовём егоJsonParser
для преобразованияJson
-строк в необходимые нам объекты. Добавим в него одинметод, который назовём
getUser(String response)
:JsonParser.java
Мы будем использовать этот метод внутри класса
HttpClient
, передавая в него ответ от сервера в форматеString
, возвращая объектUser
. Давайтеразберём преобразование, рассмотрим структура хранения
JSON
. В прошлом уроке мы в конце вывели ответ от сервера вlog
и увидели очень большой объектJSON
.На данном этапе нам необходимы только те поля, которые мы отображаем на экране. Поэтому опустим остальные поля и оставим только те, которые нам нужны:
user_info.json
Видим, что наш
JSON
полностью повторяет структуру нашего объектаUser
. Теперь можно приступить к парсингу (преобразованию) данных.Первое, что необходимо сделать – это создать
JSON
объект из строки:JsonParser.java
Видим, что
AndroidStudio
подчёркивает эту строку, указывая что надо обработать исключение или добавить его к сигнатуре метода. Можем нажатьalt + enter
и увидеть два этих варианта решения проблемы. Добавим исключение к сигнатуре, чтобы обработать исключения в клиентском коде. Для этого выберем вариант
Add exception to method signature
:JSONObject
представляет из себя структуру типаHashMap
(ключ – значение).Т.е. чтобы получить значения поля
id
нам необходимо выполнить вызов методаuserJson.getLong("id")
(получить значение типаlong
по ключу (названию поля)id
). Давайте сделаем тоже самое для каждого поля.После этого метод будет выглядеть так:
JsonParser.java
Т.е. вот так по названию поля мы можем достать его значение. Нам попался самый простой случай, где наши значения являются примитивными типами. На практике мы
поработаем с массивами элементов и вложенными объектами.
Давайте создадим объект
User
, передав ему в конструктор все поля, которые мы только что достали изuserJson
:JsonParser.java
Вот и всё! Теперь давайте добавим использование нашего класса внутри класса
HttpClient
.HttpClient.java
Добавили
JsonParser
какfinal
поле в классеHttpClient
и инициализируем его в конструкторе.После этого добавили строку
User user = jsonParser.getUser(response);
в конец методаgetUserInfo
и поменяли возвращаемый тип наUser
и добавили новоеисключение
JSONException
в сигнатуру метода. Отлично, теперь изменим код вUserInfoActivity
и запустим приложение.в
UserInfoActivity
нам нужно изменить методloadUserInfo
:UserInfoActivity.java
Мы изменили:
Возвращаемый тип
Asynctask
соString
наUser
.Добавили в
catch
блок перехват исключения типаIOException | JSONException
.В
onPostExecute
мы заменили вызовLog.d()
на вызов реального метода отображенияdisplayUserInfo(user)
.Давайте запустим наше приложение:
Всё работает! Только видим, что наш ник выводится без символа
@
. Давайте изменим методgetNick()
в классеUser
. Будем добавлять в него символ@
самостоятельно, т.к. сервер этого не сделал.User.java
Запустим наше приложение и увидим, что теперь с форматом поля
nick
всё в порядке:Полный листинг кода:
HttpClient.java
JsonParser.java
UserInfoActivity.java
Поздравляем, вы только что закончили полный цикл работы с сервером. Давайте подведём итоги:
Формат
JSON
широко используется для обмена данными между клиентом и серверомЭтот формат не привязан ни к какой технологии, поэтому он так широко используется
Структура данных представляет из себя
ключ - значение
, что позволяет удобно работать с нимВ
Android
есть классJSONObject
, который позволяет парситьJSON
в любой необходимый формат данныхСсылки:
Полезные материалы: