Parsing — процесс синтаксического анализа структурированных данных, извлекающий информацию из JSON, XML, CSV или Protobuf для использования в приложении. По данным Square Engineering (2025), выбор стратегии парсинга напрямую влияет на производительность мобильного приложения. Потоковый парсинг позволяет обрабатывать мегабайты данных без загрузки всего документа в память.
Главное
Парсинг (синтаксический анализ) — процесс преобразования последовательности символов в структурированное представление, пригодное для программной обработки. В контексте мобильной разработки под парсингом понимают разбор ответов сервера, конфигурационных файлов, локального кэша и файлов ресурсов. Каждый формат требует собственного подхода: JSON — лёгкий и встроенный в SDK, XML — строгий с валидацией схемы XSD, CSV — минималистичный для табличных данных, Protobuf — бинарный с жёсткой схемой.
Любой парсер, независимо от формата, проходит три этапа. Лексический анализ разбивает сырой текст на лексемы: ключи, строки, числа, разделители и комментарии. Синтаксический анализ проверяет корректность грамматики — баланс скобок в JSON, правильность вложенности тегов в XML. Построение выходной структуры формирует объектное представление: JSONObject, Map, или поток токенов для дальнейшей обработки. По данным Apple (2026), встроенный Foundation-парсер на iOS использует ленивый разбор — он валидирует только начало JSON, экономя ресурсы.
Ручной парсинг (JSONSerialization, XmlPullParser) даёт полный контроль над процессом и полезен при нестандартных форматах или необходимости кастомной валидации каждого поля. Автоматические библиотеки (JSONDecoder, Moshi, kotlinx.serialization) ускоряют разработку, но скрывают детали обработки ошибок. Выбор зависит от требований: если структура данных динамическая или заранее неизвестна — ручной парсинг предпочтительнее. Если схема фиксирована — автоматическая десериализация сокращает код на 60-70%.
Парсинг — более широкая операция: он может выполняться потоково и не обязательно создаёт типизированный объект. Десериализация — частный случай парсинга, результатом которого всегда является экземпляр заранее известного класса с конкретными типами свойств. Парсер JSON разберёт документ на Map или JsonElement, а десериализатор превратит тот же JSON в конкретный объект User, Order или Product с известными полями и их типами.
| Характеристика | Парсинг | Десериализация |
|---|---|---|
| Результат | JsonElement, Map, поток токенов | Типизированный объект (User, Order) |
| Потоковый режим | Да (SAX, JsonReader) | Нет (весь объект в память) |
| Типизация | Необязательна, dynamic types | Обязательна, статические типы |
| Пример | XmlPullParser.next(), SAX events | json.decodeFromString<User>() |
Потоковый парсинг — главное преимущество парсинга над десериализацией. XmlPullParser на Android разбирает XML по мере чтения, не загружая весь документ в оперативную память. Это критично для больших ответов API, парсинга RSS-лент с сотнями элементов или обработки массива из тысяч объектов JSON из серверного дампа. Потоковый парсер читает токен за токеном, потребляя константное количество памяти вне зависимости от размера документа.
JSON — доминирующий формат обмена данными. На iOS встроенный JSONSerialization разбирает JSON в Any, а JSONDecoder — сразу в Codable-структуру. На Android стандартный org.json предоставляет JSONObject и JSONArray для ручного разбора. Gson и Moshi добавляют автоматическое преобразование. Выбор между ручным и автоматическим подходом — первое архитектурное решение сетевого слоя.
val jsonString = """{"users":[{"id":1,"name":"Alice"}]}"""
val jsonObject = JSONObject(jsonString)
val usersArray = jsonObject.getJSONArray("users")
for (i in 0 until usersArray.length()) {
val item = usersArray.getJSONObject(i)
val id = item.getInt("id")
val name = item.getString("name")
// обработка пользователя
}
Ручной парсинг через org.json полезен, когда структура ответа заранее неизвестна или сильно варьируется. Такой подход даёт полный контроль над обработкой ошибок и nullable-полей, но требует больше шаблонного кода по сравнению с автоматической десериализацией. Для небольших проектов или прототипов это приемлемо, но в production предпочтительнее Moshi или kotlinx.serialization.
JsonReader из библиотеки Moshi — мощный инструмент потокового парсинга JSON. Он читает документ токен за токеном, используя методы beginObject, nextName, nextString, nextInt и endObject. Такой подход позволяет обрабатывать документы любого размера с константным потреблением памяти. По данным Google (2026), потоковый парсинг через JsonReader в 2-3 раза быстрее загрузки всего документа в JsonObject и потребляет до 80% меньше памяти.
val reader = JsonReader(StringReader(json))
reader.beginObject()
while (reader.hasNext()) {
val name = reader.nextName()
when (name) {
"id" -> val id = reader.nextInt()
"name" -> val name = reader.nextString()
"email" -> val email = reader.nextString()
else -> reader.skipValue()
}
}
reader.endObject()
В примере показан JsonReader, разбирающий JSON потоково. Каждый вызов nextName() и nextInt() продвигает курсор на следующий токен. skipValue() пропускает ненужные поля без их разбора — это особенно полезно, когда JSON содержит 50 полей, а нужны только 3. Результат — минимальное потребление памяти и максимальная скорость.
XML продолжает использоваться в Android-проектах для ресурсов и в SOAP-сервисах корпоративных приложений. На Android встроенный XmlPullParser обеспечивает потоковый разбор с минимальным потреблением памяти — он не загружает DOM-дерево, а генерирует события START_TAG, TEXT, END_TAG. iOS использует XMLParser с делегатным подходом: методы parser(didStartElement:) и parser(foundCharacters:) обрабатывают элементы последовательно.
CSV — простейший формат для экспорта и импорта табличных данных. В мобильных приложениях CSV используется для выгрузки отчётов, загрузки справочников (списки стран, валют, кодов) и синхронизации офлайн-данных. Для парсинга CSV подходят потоковые библиотеки: Apache Commons CSV и OpenCSV обрабатывают файлы строка за строкой, экранируя кавычки и запятые внутри значений. На iOS CSV-парсинг можно реализовать через делимитер NSString.components(separatedBy:) с обработкой крайних случаев.
class CSVParser: NSObject, XMLParserDelegate {
private var currentItem: [String: String] = [:]
private var currentElement: String = ""
func parser(
_ parser: XMLParser,
didStartElement elementName: String,
namespaceURI: String?,
qualifiedName qName: String?,
attributes attributeDict: [String: String]
) {
currentElement = elementName
if elementName == "item" {
currentItem = [:]
}
}
func parser(_ parser: XMLParser,
foundCharacters string: String) {
currentItem[currentElement] = string
}
}
Пример делегата XMLParser на iOS для разбора RSS-ленты. Метод didStartElement вызывается на каждом открывающем теге, foundCharacters возвращает текстовое содержимое между тегами, didEndElement завершает элемент. Такая событийная архитектура позволяет обрабатывать XML любого размера без загрузки DOM-дерева в память — критично для ограниченных ресурсов мобильных устройств.
На Android выбор CSV-парсера зависит от объёма данных. OpenCSV поддерживает fluent API, аннотации для маппинга на POJO и кастомные разделители. Apache Commons CSV — более низкоуровневый, но быстрее на больших файлах. Для простых случаев (1-2 колонки) достаточно ручного разбора через String.split(",") с обработкой экранирования. Для production-проектов с большими CSV-файлами рекомендуется OpenCSV.
Protocol Buffers от Google — бинарный формат сериализации, превосходящий JSON по скорости и компактности. Protobuf-сообщение занимает в 3-6 раз меньше места, чем эквивалентный JSON, и парсится в 4-10 раз быстрее благодаря бинарному формату и жёсткой схеме. Основные недостатки: отсутствие человекочитаемости и необходимость генерации кода из .proto-файлов через protoc-компилятор.
Потоковый парсинг Protobuf реализуется через CodedInputStream — клиент читает поля по мере поступления без загрузки всего сообщения. Каждое поле имеет tag (номер + тип), и парсер может пропускать неизвестные поля. По данным Google (2026), потоковый разбор Protobuf потребляет до 90% меньше памяти при обработке сообщений от 1 МБ, что критично для мобильных устройств с ограниченной оперативной памятью. Protobuf-lite — специальная версия для Android, оптимизированная по размеру сгенерированного кода.
Часто задаваемые вопросы
JSONSerialization — ручной парсинг, возвращающий Any (Dictionary, Array) без типизации. JSONDecoder — автоматическая десериализация в Codable-типы. JSONSerialisation даёт гибкость для динамических структур, JSONDecoder — скорость и типовую безопасность для известных схем. В production рекомендуется JSONDecoder.
Потоковый парсинг обязателен при ответах от 500 КБ, при парсинге RSS/Atom лент и при разборе файлов на устройствах с ограниченной памятью. Для типовых API-ответов до 100 КБ автоматическая десериализация через JSONDecoder или Moshi предпочтительнее — код чище и быстрее разрабатывается.
Android SDK включает org.json (JSONObject, JSONArray), XmlPullParser (XML) и android.util.JsonReader. Для CSV, YAML и Protobuf требуются дополнительные библиотеки: OpenCSV для CSV, SnakeYAML для YAML, protobuf-javalite для Protobuf.
Используйте lenient режим в kotlinx.serialization или JsonReader.setLenient(true) в Moshi — он прощает лишние запятые, неэкранированные кавычки и однострочные комментарии. Для полной валидации внедрите контрактное тестирование через Pact или Spring Cloud Contract.
SAX (Simple API for XML) — потоковый XML-парсер, генерирующий события startElement, characters, endElement при обходе документа. Реализован через XmlPullParser на Android и XMLParser на iOS. Применяется в RSS-ридерах, синхронизации офлайн-данных и обработке SVG-файлов.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также