Урок 14. Знакомство с форматом JSON. Парсинг JsonObject на примере объекта User
В этом уроке мы с вами более подробно познакомимся с форматом JSON . А потом из этого формата получим наш User объект.
JSON стал общепринятым форматом для обмена данными в клиент-серверных приложения. Он является универсальным форматом для обмена данными.
Представьте, что вам нужно создать систему приложений, в которую входит, сервер, web -клиент, ios -клиент, android -клиент. У всех технологий разные языки,
разные особенности. Поэтому сервер отвечает в формате JSON , а клиенты на своей стороне приводят к нужному формату ответы. Подробнее про JSON формат можно
почитать здесь, но на данном этапе ваших знаний уже вполне хватит.
JSONObject, работа с JSON в java коде
Давайте создадим новый класс в пакете network и назовём его JsonParser для преобразования Json -строк в необходимые нам объекты. Добавим в него один
метод, который назовём getUser(String response) :
Мы будем использовать этот метод внутри класса HttpClient , передавая в него ответ от сервера в формате String , возвращая объект User . Давайте
разберём преобразование, рассмотрим структура хранения JSON . В прошлом уроке мы в конце вывели ответ от сервера в log и увидели очень большой объект JSON .
На данном этапе нам необходимы только те поля, которые мы отображаем на экране. Поэтому опустим остальные поля и оставим только те, которые нам нужны:
Видим, что наш JSON полностью повторяет структуру нашего объекта User . Теперь можно приступить к парсингу (преобразованию) данных.
Первое, что необходимо сделать – это создать JSON объект из строки:
Видим, что AndroidStudio подчёркивает эту строку, указывая что надо обработать исключение или добавить его к сигнатуре метода. Можем нажать alt + enter
и увидеть два этих варианта решения проблемы. Добавим исключение к сигнатуре, чтобы обработать исключения в клиентском коде. Для этого выберем вариант Add exception to method signature :
JSONObject представляет из себя структуру типа HashMap (ключ – значение).
Т.е. чтобы получить значения поля id нам необходимо выполнить вызов метода
userJson.getLong(«id») (получить значение типа long по ключу (названию поля) id ). Давайте сделаем тоже самое для каждого поля.
После этого метод будет выглядеть так:
Т.е. вот так по названию поля мы можем достать его значение. Нам попался самый простой случай, где наши значения являются примитивными типами. На практике мы
поработаем с массивами элементов и вложенными объектами.
Давайте создадим объект User , передав ему в конструктор все поля, которые мы только что достали из userJson :
Вот и всё! Теперь давайте добавим использование нашего класса внутри класса HttpClient .
Добавили JsonParser как final поле в классе HttpClient и инициализируем его в конструкторе.
После этого добавили строку User user = jsonParser.getUser(response); в конец метода getUserInfo и поменяли возвращаемый тип на User и добавили новое
исключение JSONException в сигнатуру метода. Отлично, теперь изменим код в UserInfoActivity и запустим приложение.
в UserInfoActivity нам нужно изменить метод loadUserInfo :
Возвращаемый тип Asynctask со String на User .
Добавили в catch блок перехват исключения типа IOException | JSONException .
В onPostExecute мы заменили вызов Log.d() на вызов реального метода отображения displayUserInfo(user) .
Давайте запустим наше приложение:
Всё работает! Только видим, что наш ник выводится без символа @ . Давайте изменим метод getNick() в классе User . Будем добавлять в него символ @ самостоятельно, т.к. сервер этого не сделал.
Запустим наше приложение и увидим, что теперь с форматом поля nick всё в порядке:
Источник
Android — сохранить JSON из InputStream в строку
Я пытаюсь проанализировать этот JSON, который я получаю из HttpURLConnection в Android.
То, что я хочу сделать, это сохранить содержимое value1 в строке, содержимое value2 в другой строке. потому что мне нужно сохранить его в базе данных, поэтому в будущем я могу загрузить и проанализировать его. Я использую JsonReader, но это невозможно сделать с помощью JsonReader.
Есть идеи? Пользовательские объекты невозможны, потому что мы никогда не знаем, какие значения JSON покажет.
8 ответов
Используйте это для преобразования массива JSON в строку
Этот код работает для вашего примера JSON.
Используйте Gson для анализа JSON, который вы получаете в InputStream. Затем вы можете получить ArrayList из этого проанализированного объекта. Снова используйте Gson для сериализации массива обратно в JSON.
Просто регулярно читайте поток и сохраняйте его в обычную строку, а затем анализируйте эту строку:
теперь у вас есть все значения (какими бы ни были их идентификаторы имен), объединенные в этот ArrayList с именем (all_values).
Обратите внимание, что в JSON, который вы указали в своем вопросе, отсутствуют открывающие скобки «<" и закрывающие ">» в начале и конце.
Поскольку вы заранее не знаете структуру json, лучше всего использовать функцию GSON 2.0, которая поддерживает карты и списки по умолчанию. Используйте следующий код для десериализации:
Созданный объект — это карта (com.google.gson.internal.LinkedTreeMap), которая выглядит следующим образом (для приведенного выше примера)
Используйте сгенерированный объект, проанализируйте его и сохраните в своей базе данных. Вы можете сериализовать эту карту обратно в JSON, используя:
Надеюсь, это поможет вам.
Что вам нужно сделать, так это сначала создать JsonObject из строкового представления json, на данном этапе никаких подробностей не дается.
Интересно, что вы упомянули, что структура меняется, она считает странным, я предполагаю, что вы используете разные экземпляры API. Что вам нужно сделать, создать класс pojo, отображающий имя экземпляра API в тело возвращенной строки json.
После того, как вы достигли интересующего вас объекта, рассмотрите возможность использования GSON. Библиотека сериализации / десериализации Java для преобразования объектов Java в JSON и обратно. Затем вам нужно сериализовать класс pojo в объект. Затем сохранить в базе данных. Я рекомендую использовать область, а не SQLite.
Пример сериализации класса.
затем получите объект json String и сохраните его в выбранной базе данных.
Источник
KengoTODA / JSONInputStream.diff
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
diff —git a/JSONInputStream.java b/JSONInputStream.java |
new file mode 100644 |
index 0000000..93708ff |
— /dev/null |
+++ b/JSONInputStream.java |
@@ -0,0 +1,75 @@ |
+ package org.json; |
+ |
+ import java.io.ByteArrayInputStream; |
+ import java.io.ByteArrayOutputStream; |
+ import java.io.IOException; |
+ import java.io.InputStream; |
+ import java.io.OutputStreamWriter; |
+ import java.nio.charset.Charset; |
+ import java.util.Iterator; |
+ |
+ public class JSONInputStream extends InputStream < |
+ |
+ private final Iterator keyIterator; |
+ private final JSONObject source; |
+ private ByteArrayInputStream buffer = new ByteArrayInputStream(» <".getBytes()); |
+ private boolean isFinished = false; |
+ private boolean commanate = false; |
+ private final Charset charset; |
+ |
+ public JSONInputStream(JSONObject object) < |
+ this(object, Charset.defaultCharset()); |
+ > |
+ |
+ @SuppressWarnings(«unchecked») |
+ public JSONInputStream(JSONObject object, Charset charset) < |
+ if (object == null || charset == null) < |
+ throw new NullPointerException(); |
+ > |
+ this.keyIterator = object.keys(); |
+ this.source = object; |
+ this.charset = charset; |
+ > |
+ |
+ @Override |
+ public int read() throws IOException < |
+ if (this.isFinished) < |
+ return -1; |
+ > |
+ |
+ int result = buffer.read(); |
+ if (result == -1) < |
+ loadNextToBuffer(); |
+ commanate = true; |
+ result = buffer == null ? -1 : buffer.read(); |
+ if (result == -1) < |
+ // finish loading all keys |
+ this.isFinished = true; |
+ result = ‘>’; |
+ > |
+ > |
+ return result; |
+ > |
+ |
+ private void loadNextToBuffer() throws IOException < |
+ if (!keyIterator.hasNext()) < |
+ buffer = null; |
+ return; |
+ > |
+ |
+ ByteArrayOutputStream output = new ByteArrayOutputStream(); |
+ OutputStreamWriter writer = new OutputStreamWriter(output, charset); |
+ if (commanate) < |
+ writer.write(«,»); |
+ > |
+ Object key = keyIterator.next(); |
+ try < |
+ source.writeContent(writer, key); |
+ > catch (JSONException e) < |
+ throw new IOException(«JSONException occurred when creating String from JSONObject», e); |
+ > |
+ writer.flush(); |
+ this.buffer = new ByteArrayInputStream(output.toByteArray()); |
+ > |
+ |
+ > |
diff —git a/JSONObject.java b/JSONObject.java |
old mode 100755 |
new mode 100644 |
index a2b3edf..62066af |
— a/JSONObject.java |
+++ b/JSONObject.java |
@@ -1611,16 +1611,7 @@ public class JSONObject < |
writer.write(‘,’); |
> |
Object key = keys.next(); |
— writer.write(quote(key.toString())); |
— writer.write(‘:’); |
— Object value = this.map.get(key); |
— if (value instanceof JSONObject) < |
— ((JSONObject)value).write(writer); |
— > else if (value instanceof JSONArray) < |
— ((JSONArray)value).write(writer); |
— > else < |
— writer.write(valueToString(value)); |
— > |
+ writeContent(writer, key); |
commanate = true; |
> |
writer.write(‘>’); |
@@ -1629,4 +1620,17 @@ public class JSONObject < |
throw new JSONException(exception); |
> |
> |
+ |
+ void writeContent(Writer writer, Object key) throws IOException, JSONException < |
+ writer.write(quote(key.toString())); |
+ writer.write(‘:’); |
+ Object value = this.map.get(key); |
+ if (value instanceof JSONObject) < |
+ ((JSONObject)value).write(writer); |
+ > else if (value instanceof JSONArray) < |
+ ((JSONArray)value).write(writer); |
+ > else < |
+ writer.write(valueToString(value)); |
+ > |
+ > |
> |
\ No newline at end of file |
diff —git a/Test.java b/Test.java |
old mode 100755 |
new mode 100644 |
index 4cd1ace..4d01f8b |
— a/Test.java |
+++ b/Test.java |
@@ -5,7 +5,13 @@ import java.util.Collection; |
import java.util.Iterator; |
import java.util.List; |
import java.util.Map; |
+ import java.io.ByteArrayOutputStream; |
+ import java.io.IOException; |
+ import java.io.InputStreamReader; |
+ import java.io.OutputStreamWriter; |
import java.io.StringWriter; |
+ import java.nio.charset.Charset; |
+ |
import junit.framework.TestCase; |
/* |
@@ -859,6 +865,31 @@ public class Test extends TestCase < |
> |
> |
+ public void testJSONInputStream() throws JSONException, IOException < |
+ for (String pattern : new String[] < |
+ «<>«, «<\"message\":\"value\">«, « |
+ «<\"0\":0>«,»<\"null\":null>«,»<\"multiline\":\"1\\r\\n2\\r3\\n4\">« |
+ >) < |
+ JSONObject jsonObject = new JSONObject(pattern); |
+ JSONInputStream stream = new JSONInputStream(jsonObject, Charset.forName(«UTF-8»)); |
+ assertEquals(jsonObject.toString(), createStringFrom(stream)); |
+ > |
+ > |
+ |
+ private String createStringFrom(JSONInputStream input) throws IOException < |
+ assert input != null; |
+ InputStreamReader reader = new InputStreamReader(input); |
+ ByteArrayOutputStream output = new ByteArrayOutputStream(); |
+ OutputStreamWriter writer = new OutputStreamWriter(output); |
+ char[] buffer = new char[1024]; |
+ int length; |
+ while ((length = reader.read(buffer)) != -1) < |
+ writer.write(buffer, 0, length); |
+ > |
+ writer.flush(); |
+ return output.toString(); |
+ > |
+ |
/** |
* Beany is a typical class that implements JSONString. It also |
* provides some beany methods that can be used to |
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Источник