JSON формат
В этом уроке мы с вами более подробно познакомимся с форматом JSON . А потом из этого формата получим наш User объект.
JSON стал общепринятым форматом для обмена данными в клиент-серверных приложения. Он является универсальным форматом для обмена данными.
Представьте, что вам нужно создать систему приложений, в которую входит, сервер, web -клиент, ios -клиент, android -клиент. У всех технологий разные языки,
разные особенности. Поэтому сервер отвечает в формате JSON , а клиенты на своей стороне приводят к нужному формату ответы. Подробнее про JSON формат можно
почитать здесь, но на данном этапе ваших знаний уже вполне хватит.
JSONObject, работа с JSON в java коде
Давайте создадим новый класс в пакете network и назовём его JsonParser для преобразования Json -строк в необходимые нам объекты. Добавим в него один
метод, который назовём getUser(String response) :
1 2 3 4 5 6 7 8 9 10
package colibri.dev.com.colibritweet.network; import colibri.dev.com.colibritweet.pojo.User; public class JsonParser public User getUser(String response) return null; > >
Мы будем использовать этот метод внутри класса HttpClient , передавая в него ответ от сервера в формате String , возвращая объект User . Давайте
разберём преобразование, рассмотрим структура хранения JSON . В прошлом уроке мы в конце вывели ответ от сервера в log и увидели очень большой объект JSON .
На данном этапе нам необходимы только те поля, которые мы отображаем на экране. Поэтому опустим остальные поля и оставим только те, которые нам нужны:
1 2 3 4 5 6 7 8 9 10
< "id": 929257819349700600, "name": "Devcolibri", "screen_name": "devcolibri", "location": "Republic of Belarus", "description": "Образовательный IT-портал. Android, Java, Kotlin.", "profile_image_url": "http://pbs.twimg.com/profile_images/929258919402377216/JDAtj1H__normal.jpg", "followers_count": 5, "favourites_count": 0, >
Видим, что наш JSON полностью повторяет структуру нашего объекта User . Теперь можно приступить к парсингу (преобразованию) данных.
Первое, что необходимо сделать – это создать JSON объект из строки:
1 2 3 4 5 6 7 8 9 10 11
package colibri.dev.com.colibritweet.network; import colibri.dev.com.colibritweet.pojo.User; public class JsonParser public User getUser(String response) JSONObject userJson = new JSONObject(response); return null; > >
Видим, что AndroidStudio подчёркивает эту строку, указывая что надо обработать исключение или добавить его к сигнатуре метода. Можем нажать alt + enter
и увидеть два этих варианта решения проблемы. Добавим исключение к сигнатуре, чтобы обработать исключения в клиентском коде. Для этого выберем вариант Add exception to method signature :
JSONObject представляет из себя структуру типа HashMap (ключ – значение).
Т.е. чтобы получить значения поля id нам необходимо выполнить вызов метода
userJson.getLong(«id») (получить значение типа long по ключу (названию поля) id ). Давайте сделаем тоже самое для каждого поля.
После этого метод будет выглядеть так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public class JsonParser 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"); return null; > >
Т.е. вот так по названию поля мы можем достать его значение. Нам попался самый простой случай, где наши значения являются примитивными типами. На практике мы
поработаем с массивами элементов и вложенными объектами.
Давайте создадим объект User , передав ему в конструктор все поля, которые мы только что достали из userJson :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public class JsonParser 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"); return new User(id, imageUrl, name, nick, description, location, followingCount, followersCount); > >
Вот и всё! Теперь давайте добавим использование нашего класса внутри класса HttpClient .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
public class HttpClient private static final String HEADER_AUTHORIZATION = "Authorization"; private static final String GET = "GET"; private final JsonParser jsonParser; public HttpClient() 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 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
public class UserInfoActivity extends AppCompatActivity // остальной код выше не изменился @SuppressLint("StaticFieldLeak") private void loadUserInfo(final Long userId) new AsyncTaskVoid, Void, User>() @Override protected User doInBackground(Void. voids) try return httpClient.readUserInfo(userId); > catch (IOException | JSONException e) e.printStackTrace(); return null; > > @Override protected void onPostExecute(User user) displayUserInfo(user); > >.execute(); > // остальной код ниже не изменился >
- Возвращаемый тип Asynctask со String на User .
- Добавили в catch блок перехват исключения типа IOException | JSONException .
- В onPostExecute мы заменили вызов Log.d() на вызов реального метода отображения displayUserInfo(user) .
Давайте запустим наше приложение:

Всё работает! Только видим, что наш ник выводится без символа @ . Давайте изменим метод getNick() в классе User . Будем добавлять в него символ @ самостоятельно, т.к. сервер этого не сделал.
1 2 3 4 5 6 7 8 9 10
public class User // Остальной код выше не изменился public String getNick() return "@" + nick; > // Остальной код ниже не изменился >
Запустим наше приложение и увидим, что теперь с форматом поля nick всё в порядке:

Полный листинг кода:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
package colibri.dev.com.colibritweet.network; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import com.twitter.sdk.android.core.TwitterAuthConfig; import com.twitter.sdk.android.core.TwitterCore; import com.twitter.sdk.android.core.TwitterSession; import com.twitter.sdk.android.core.internal.oauth.OAuth1aHeaders; import org.json.JSONException; import colibri.dev.com.colibritweet.pojo.User; public class HttpClient private static final String HEADER_AUTHORIZATION = "Authorization"; private static final String GET = "GET"; private final JsonParser jsonParser; public HttpClient() 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; > private String convertStreamToString(InputStream stream) throws IOException BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) sb.append(line).append("\n"); > stream.close(); return sb.toString(); > private String getAuthHeader(String url) TwitterAuthConfig authConfig = TwitterCore.getInstance().getAuthConfig(); TwitterSession session = TwitterCore.getInstance().getSessionManager().getActiveSession(); return new OAuth1aHeaders().getAuthorizationHeader(authConfig, session.getAuthToken(), null, GET, url, null); > >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
package colibri.dev.com.colibritweet.network; import org.json.JSONException; import org.json.JSONObject; import colibri.dev.com.colibritweet.pojo.User; public class JsonParser 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"); return new User(id, imageUrl, name, nick, description, location, followingCount, followersCount); > >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
package colibri.dev.com.colibritweet.activity; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import android.annotation.SuppressLint; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.widget.ImageView; import android.widget.TextView; import com.squareup.picasso.Picasso; import org.json.JSONException; import colibri.dev.com.colibritweet.R; import colibri.dev.com.colibritweet.adapter.TweetAdapter; import colibri.dev.com.colibritweet.network.HttpClient; import colibri.dev.com.colibritweet.pojo.Tweet; import colibri.dev.com.colibritweet.pojo.User; public class UserInfoActivity extends AppCompatActivity private ImageView userImageView; private TextView nameTextView; private TextView nickTextView; private TextView descriptionTextView; private TextView locationTextView; private TextView followingCountTextView; private TextView followersCountTextView; private RecyclerView tweetsRecyclerView; private TweetAdapter tweetAdapter; private Toolbar toolbar; private HttpClient httpClient; @Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState); setContentView(R.layout.activity_user_info); long userId = getIntent().getLongExtra(AuthActivity.USER_ID, -1); userImageView = findViewById(R.id.user_image_view); nameTextView = findViewById(R.id.user_name_text_view); nickTextView = findViewById(R.id.user_nick_text_view); descriptionTextView = findViewById(R.id.user_description_text_view); locationTextView = findViewById(R.id.user_location_text_view); followingCountTextView = findViewById(R.id.following_count_text_view); followersCountTextView = findViewById(R.id.followers_count_text_view); toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); initRecyclerView(); httpClient = new HttpClient(); loadUserInfo(userId); loadTweets(); > @Override public boolean onCreateOptionsMenu(Menu menu) getMenuInflater().inflate(R.menu.user_info_menu, menu); return true; > @Override public boolean onOptionsItemSelected(MenuItem item) if(item.getItemId() == R.id.action_search) Intent intent = new Intent(this, SearchUsersActivity.class); startActivity(intent); > return true; > private void loadTweets() CollectionTweet> tweets = getTweets(); tweetAdapter.setItems(tweets); > private CollectionTweet> getTweets() return Arrays.asList( new Tweet(getUser(), 1L, "Thu Dec 13 07:31:08 +0000 2017", "Очень длинное описание твита 1", 4L, 4L, "https://www.w3schools.com/w3css/img_fjords.jpg"), new Tweet(getUser(), 2L, "Thu Dec 12 07:31:08 +0000 2017", "Очень длинное описание твита 2", 5L, 5L, "https://www.w3schools.com/w3images/lights.jpg"), new Tweet(getUser(), 3L, "Thu Dec 11 07:31:08 +0000 2017", "Очень длинное описание твита 3", 6L, 6L, "https://www.w3schools.com/css/img_mountains.jpg") ); > private void initRecyclerView() tweetsRecyclerView = findViewById(R.id.tweets_recycler_view); tweetsRecyclerView.setLayoutManager(new LinearLayoutManager(this)); tweetAdapter = new TweetAdapter(); tweetsRecyclerView.setAdapter(tweetAdapter); > @SuppressLint("StaticFieldLeak") private void loadUserInfo(final Long userId) new AsyncTaskVoid, Void, User>() @Override protected User doInBackground(Void. voids) try return httpClient.readUserInfo(userId); > catch (IOException | JSONException e) e.printStackTrace(); return null; > > @Override protected void onPostExecute(User user) displayUserInfo(user); > >.execute(); > private void displayUserInfo(User user) Picasso.with(this).load(user.getImageUrl()).into(userImageView); nameTextView.setText(user.getName()); nickTextView.setText(user.getNick()); descriptionTextView.setText(user.getDescription()); locationTextView.setText(user.getLocation()); String followingCount = String.valueOf(user.getFollowingCount()); followingCountTextView.setText(followingCount); String followersCount = String.valueOf(user.getFollowersCount()); followersCountTextView.setText(followersCount); getSupportActionBar().setTitle(user.getName()); > private User getUser() return new User( 1L, "http://i.imgur.com/DvpvklR.png", "DevColibri", "devcolibri", "Sample description", "USA", 42, 42 ); > >
Поздравляем, вы только что закончили полный цикл работы с сервером. Давайте подведём итоги:
- Формат JSON широко используется для обмена данными между клиентом и сервером
- Этот формат не привязан ни к какой технологии, поэтому он так широко используется
- Структура данных представляет из себя ключ — значение , что позволяет удобно работать с ним
- В Android есть класс JSONObject , который позволяет парсить JSON в любой необходимый формат данных
- Русскоязычные:
- Что такое JSON
- Официальная документация. JSONObject
Парсинг JSON с помощью JSON simple -выдает ошибку. Не могу победить 2 день. Поможайте!
Всем доброго, друзья! У меня тут такая задачка, с которой бьюсь второй день и не могу победить. В чем может быть проблема, на ваш взгляд: 1) есть файл JSON:
"tickets": [ "origin": "VVO", "origin_name": "Владивосток", "destination": "TLV", "destination_name": "Тель-Авив", "departure_date": "12.05.18", "departure_time": "16:20", "arrival_date": "12.05.18", "arrival_time": "22:10", "carrier": "TK", "stops": 3, "price": 12400 >, "origin": "VVO", "origin_name": "Владивосток", "destination": "TLV", "destination_name": "Тель-Авив", "departure_date": "12.05.18", "departure_time": "6:10", "arrival_date": "12.05.18", "arrival_time": "16:15", "carrier": "S7", "stops": 0, "price": 17400 >] >Пытаюсь его парсить так:
public static void main(String[] args) throws IOException, ParseException Object obj = new JSONParser().parse(new FileReader("c:/tickets.json")); JSONObject jo = (JSONObject) obj; JSONArray ticketsArr = (JSONArray) jo.get("tickets"); Iterator ticketsItr = ticketsArr.iterator(); System.out.println("tickets:"); while (ticketsItr.hasNext()) JSONObject test = (JSONObject) ticketsItr.next(); System.out.println("- tickets: " + test.get("departure_time") ); > Постоянно выдает ошибку: "Exception in thread "main" Unexpected character () at position 0." Не могу понять, в чем беда... >JSON.parse()
Метод JSON.parse() разбирает строку JSON, возможно с преобразованием получаемого в процессе разбора значения.
Синтаксис
JSON.parse(text[, reviver])
Параметры
Разбираемая строка JSON. Смотрите документацию по объекту JSON для описания синтаксиса JSON.
Если параметр является функцией, определяет преобразование полученного в процессе разбора значения, прежде, чем оно будет возвращено вызывающей стороне.
Возвращаемое значение
Возвращает объект Object , соответствующий переданной строке JSON text .
Выбрасываемые исключения
Выбрасывает исключение SyntaxError , если разбираемая строка не является правильным JSON.
Примеры
Пример: использование метода JSON.parse()
JSON.parse("<>"); // <> JSON.parse("true"); // true JSON.parse('"foo"'); // "foo" JSON.parse('[1, 5, "false"]'); // [1, 5, "false"] JSON.parse("null"); // null
Пример: использование параметра reviver
Если определён параметр reviver , значение, вычисляемое при разборе строки, будет преобразовано перед его возвратом. В частности, вычисленное значение и все его свойства (начиная с самых вложенных свойств и кончая самим значением), каждое проходят через функцию reviver , которая вызывается с контекстом this , содержащим объект в виде обрабатываемого свойства, и с аргументами: именем свойства в виде строки и значением свойства. Если функция reviver вернёт undefined (либо вообще не вернёт никакого значения, например, если выполнение достигнет конца функции), свойство будет удалено из объекта. В противном случае свойство будет переопределено возвращаемым значением.
В конечном итоге, функция reviver вызывается с пустой строкой и самым верхним значением, чтобы обеспечить преобразование самого верхнего значения. Убедитесь, что вы правильно обрабатываете этот случай — обычно для этого нужно просто вернуть само значение — или метод JSON.parse() вернёт undefined .
JSON.parse('', function (k, v) if (k === "") return v; > // самое верхнее значение - возвращаем его return v * 2; // иначе возвращаем v * 2. >); // JSON.parse('>>', function (k, v) console.log(k); // пишем имя текущего свойства, последним именем будет "" return v; // возвращаем неизменённое значение свойства >); // 1 // 2 // 4 // 6 // 5 // 3 // ""
Спецификации
Specification ECMAScript Language Specification
# sec-json.parseСовместимость с браузерами
BCD tables only load in the browser
Смотрите также
- Использование родного объекта JSON (en-US)
- JSON.stringify()
JavaScript JSON Парсинг
Обычно JSON используется для обмена данными с веб сервером.
При получении данных с веб сервера они всегда представляют собой строку.
Проанализируйте данные с помощью JSON.parse() , и данные становятся объектом JavaScript.
Пример — JSON.parse()
Представьте, что мы получили этот текст с веб сервера:
Используйте функцию JavaScript JSON.parse() для преобразования текста в объект JavaScript:
var obj = JSON.parse(‘<"name":"Андрей", "age":50, "city":"Пермь">‘);"name":"Андрей",>
Убедитесь, что текст написан в формате JSON, иначе вы получите синтаксическую ошибку.
Используйте объект JavaScript на своей странице:
Пример
JSON с сервера
Вы можете запросить JSON с сервера, используя AJAX запрос
Пока ответ от сервера записан в формате JSON, вы можете проанализировать строку в объект JavaScript.
Пример
Используйте XMLHttpRequest для получения данных с сервера:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() if (this.readyState == 4 && this.status == 200) var myObj = JSON.parse(this.responseText);
document.getElementById(«demo»).innerHTML = myObj.name;
>
>;
xmlhttp.open(«GET», «json_demo.txt», true);
xmlhttp.send();JSON массив
При использовании JSON.parse() на JSON, производном от массива, метод вернет массив JavaScript, а не объект JavaScript.
Пример
JSON, возвращенный с сервера, представляет собой массив:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() if (this.readyState == 4 && this.status == 200) var myArr = JSON.parse(this.responseText);
document.getElementById(«demo»).innerHTML = myArr[0];
>
>;
xmlhttp.open(«GET», «json_demo_array.txt», true);
xmlhttp.send();Исключения
Разбор дат
Объекты дат не допускаются в JSON.
Если вам нужно включить дату, запишите ее в виде строки.
Вы можете преобразовать его обратно в объект даты позже:
Пример
Преобразование строки в дату:
document.getElementById(«demo»).innerHTML = obj.name + «, » + obj.birth;
Или вы можете использовать второй параметр JSON.parse() , называемая reviver.
Параметр reviver — это функция, которая проверяет каждое свойство перед возвращением значения.
Пример
Преобразовать строку в дату, используя функцию восстановления:
document.getElementById(«demo»).innerHTML = obj.name + «, » + obj.birth;
Парсинг функции
Функции не разрешены в JSON.
Если вам нужно включить функцию, запишите ее в виде строки.
Вы можете преобразовать его обратно в функцию позже:
Пример
Преобразование строки в функцию::
document.getElementById(«demo»).innerHTML = obj.name + «, » + obj.age();
Вы должны избегать использования функций в JSON, функции потеряют свою область действия, и вам придется использовать eval() , чтобы преобразовать их обратно в функции.
Поддержка браузеров
Функция JSON.parse() включена во все основные браузеры и в новейший стандарт ECMAScript (JavaScript).
Числа в таблице ниже указывают первую версию браузера, которая полностью поддерживает функция JSON.parse() :
Да 8.0 3.5 4.0 10.0 Для старых браузеров библиотека JavaScript доступна по адресу https://github.com/douglascrockford
Мы только что запустили
SchoolsW3 видеоВЫБОР ЦВЕТА

курс сегодня!
Сообщить об ошибке
Если вы хотите сообщить об ошибке или внести предложение, не стесняйтесь отправлять на электронное письмо:
Ваше предложение:
Спасибо Вам за то, что помогаете!
Ваше сообщение было отправлено в SchoolsW3.
ТОП Учебники
ТОП Справочники
ТОП Примеры
Получить сертификат
SchoolsW3 оптимизирован для бесплатного обучения, проверки и подготовки знаний. Примеры в редакторе упрощают и улучшают чтение и базовое понимание. Учебники, ссылки, примеры постоянно пересматриваются, чтобы избежать ошибок, но не возможно гарантировать полную правильность всего содержания. Некоторые страницы сайта могут быть не переведены на РУССКИЙ язык, можно отправить страницу как ошибку, так же можете самостоятельно заняться переводом. Используя данный сайт, вы соглашаетесь прочитать и принять Условия к использованию, Cookies и политика конфиденциальности.
