Parsing trong ứng dụng di động: bản chất, định dạng dữ liệu và quy trình

Tác giả: IT Sectr Đã đăng: 2026-03-08 Thời gian đọc: 8 phút

Parsing là quá trình phân tích cú pháp dữ liệu có cấu trúc, trích xuất thông tin từ JSON, XML, CSV hoặc Protobuf để sử dụng trong ứng dụng. Theo Square Engineering (2025), việc lựa chọn chiến lược parsing ảnh hưởng trực tiếp đến hiệu suất của ứng dụng di động. Parsing luồng cho phép xử lý hàng megabyte dữ liệu mà không cần tải toàn bộ tài liệu vào bộ nhớ.

Những điểm chính

  • Parsing — phân rã văn bản có cấu trúc thành các token để trích xuất dữ liệu mà không cần định kiểu bắt buộc.
  • JSON — định dạng phổ biến nhất cho REST API trong ứng dụng di động iOS và Android.
  • Parsing luồng tiết kiệm bộ nhớ khi xử lý tệp lớn và nguồn cấp RSS.
  • Tạo mã — tạo trình phân tích tại thời điểm biên dịch, tăng tốc thời gian chạy lên 2-4 lần.
  • Protobuf — định dạng nhị phân, nhỏ gọn hơn JSON 3-6 lần và phân tích nhanh hơn.

Parsing là gì?

Parsing (phân tích cú pháp) là quá trình chuyển đổi một chuỗi ký tự thành biểu diễn có cấu trúc phù hợp cho xử lý lập trình. Trong bối cảnh phát triển di động, parsing đề cập đến việc xử lý phản hồi máy chủ, tệp cấu hình, bộ nhớ đệm cục bộ và tệp tài nguyên. Mỗi định dạng yêu cầu cách tiếp cận riêng: JSON — nhẹ và tích hợp trong SDK, XML — nghiêm ngặt với xác thực lược đồ XSD, CSV — tối giản cho dữ liệu dạng bảng, Protobuf — nhị phân với lược đồ cứng nhắc.

Các giai đoạn phân tích cú pháp

Bất kỳ trình phân tích nào, bất kể định dạng, đều trải qua ba giai đoạn. Phân tích từ vựng chia văn bản thô thành các token: khóa, chuỗi, số, dấu phân cách và chú thích. Phân tích cú pháp kiểm tra tính đúng đắn của ngữ pháp — cân bằng dấu ngoặc trong JSON, lồng thẻ chính xác trong XML. Xây dựng cấu trúc đầu ra tạo thành biểu diễn đối tượng: JSONObject, Map hoặc luồng token để xử lý tiếp. Theo Apple (2026), trình phân tích Foundation tích hợp trên iOS sử dụng phân tích lười biếng — chỉ xác thực phần đầu của JSON, tiết kiệm tài nguyên.

Parsing thủ công vs thư viện tự động

Parsing thủ công (JSONSerialization, XmlPullParser) kiểm soát hoàn toàn quy trình và hữu ích cho các định dạng không chuẩn hoặc khi cần xác thực tùy chỉnh từng trường. Thư viện tự động (JSONDecoder, Moshi, kotlinx.serialization) tăng tốc phát triển nhưng ẩn chi tiết xử lý lỗi. Sự lựa chọn phụ thuộc vào yêu cầu: nếu cấu trúc dữ liệu động hoặc không xác định trước — parsing thủ công tốt hơn. Nếu lược đồ cố định — giải tuần tự hóa tự động giảm mã 60-70%.

Parsing khác giải tuần tự hóa như thế nào

Parsing là một thao tác rộng hơn: có thể thực hiện theo luồng và không nhất thiết tạo đối tượng được định kiểu. Giải tuần tự hóa là một trường hợp cụ thể của parsing mà kết quả luôn là một thể hiện của lớp đã biết với các kiểu thuộc tính cụ thể. Trình phân tích JSON chia tài liệu thành Map hoặc JsonElement, trong khi bộ giải tuần tự hóa chuyển cùng JSON đó thành đối tượng User, Order hoặc Product với các trường và kiểu đã biết.

Đặc điểmParsingGiải tuần tự hóa
Kết quảJsonElement, Map, luồng tokenĐối tượng được định kiểu (User, Order)
Chế độ luồngCó (SAX, JsonReader)Không (toàn bộ đối tượng trong bộ nhớ)
Định kiểuTùy chọn, kiểu độngBắt buộc, kiểu tĩnh
Ví dụXmlPullParser.next(), sự kiện SAXjson.decodeFromString<User>()

Parsing luồng là lợi thế chính của parsing so với giải tuần tự hóa. XmlPullParser trên Android phân tích XML khi đọc, mà không tải toàn bộ tài liệu vào RAM. Điều này rất quan trọng đối với phản hồi API lớn, phân tích nguồn cấp RSS với hàng trăm mục hoặc xử lý mảng hàng nghìn đối tượng JSON từ kết xuất máy chủ. Trình phân tích luồng đọc từng token một, tiêu thụ lượng bộ nhớ không đổi bất kể kích thước tài liệu.

Parsing JSON trong ứng dụng di động

JSON là định dạng trao đổi dữ liệu thống trị. Trên iOS, JSONSerialization tích hợp phân tích JSON thành Any, trong khi JSONDecoder phân tích trực tiếp thành cấu trúc Codable. Trên Android, org.json tiêu chuẩn cung cấp JSONObject và JSONArray để phân tích thủ công. Gson và Moshi thêm chuyển đổi tự động. Lựa chọn giữa cách tiếp cận thủ công và tự động là quyết định kiến trúc đầu tiên của lớp mạng.

kotlin
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")
    // xử lý người dùng
}

Parsing thủ công qua org.json hữu ích khi cấu trúc phản hồi không xác định trước hoặc thay đổi nhiều. Cách tiếp cận này kiểm soát hoàn toàn việc xử lý lỗi và trường nullable nhưng yêu cầu nhiều mã soạn sẵn hơn so với giải tuần tự hóa tự động. Đối với dự án nhỏ hoặc nguyên mẫu, điều này chấp nhận được, nhưng trong sản xuất, Moshi hoặc kotlinx.serialization được ưu tiên hơn.

JsonReader cho parsing luồng

JsonReader từ thư viện Moshi là công cụ mạnh mẽ để parsing JSON theo luồng. Nó đọc tài liệu từng token một bằng các phương thức như beginObject, nextName, nextString, nextInt và endObject. Cách tiếp cận này cho phép xử lý tài liệu ở mọi kích thước với mức tiêu thụ bộ nhớ không đổi. Theo Google (2026), parsing luồng qua JsonReader nhanh hơn 2-3 lần so với tải toàn bộ tài liệu vào JsonObject và tiêu thụ ít hơn tới 80% bộ nhớ.

kotlin
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()

Ví dụ cho thấy JsonReader phân tích JSON theo luồng. Mỗi lần gọi nextName() và nextInt() di chuyển con trỏ đến token tiếp theo. skipValue() bỏ qua các trường không cần thiết mà không phân tích chúng — đặc biệt hữu ích khi JSON chứa 50 trường nhưng chỉ cần 3. Kết quả là mức tiêu thụ bộ nhớ tối thiểu và tốc độ tối đa.

Parsing XML và CSV

XML tiếp tục được sử dụng trong các dự án Android cho tài nguyên và trong các dịch vụ SOAP của ứng dụng doanh nghiệp. Trên Android, XmlPullParser tích hợp cung cấp parsing luồng với mức tiêu thụ bộ nhớ tối thiểu — nó không tải cây DOM mà tạo ra các sự kiện START_TAG, TEXT, END_TAG. iOS sử dụng XMLParser với cách tiếp cận ủy quyền: các phương thức parser(didStartElement:) và parser(foundCharacters:) xử lý các phần tử tuần tự.

CSV trong phát triển di động

CSV là định dạng đơn giản nhất để xuất và nhập dữ liệu dạng bảng. Trong ứng dụng di động, CSV được sử dụng để xuất báo cáo, tải dữ liệu tham chiếu (danh sách quốc gia, tiền tệ, mã) và đồng bộ dữ liệu ngoại tuyến. Thư viện luồng phù hợp cho parsing CSV: Apache Commons CSVOpenCSV xử lý tệp từng dòng một, thoát dấu ngoặc kép và dấu phẩy trong giá trị. Trên iOS, parsing CSV có thể được triển khai qua phương thức phân cách NSString.components(separatedBy:) với xử lý trường hợp biên.

swift
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
    }
}

Ví dụ về bộ ủy quyền XMLParser trên iOS để phân tích nguồn cấp RSS. Phương thức didStartElement được gọi tại mỗi thẻ mở, foundCharacters trả về nội dung văn bản giữa các thẻ, didEndElement hoàn thành phần tử. Kiến trúc dựa trên sự kiện này cho phép xử lý XML ở mọi kích thước mà không cần tải cây DOM vào bộ nhớ — rất quan trọng đối với tài nguyên hạn chế trên thiết bị di động.

So sánh thư viện CSV cho Android

Trên Android, việc chọn trình phân tích CSV phụ thuộc vào khối lượng dữ liệu. OpenCSV hỗ trợ API linh hoạt, chú thích cho ánh xạ POJO và dấu phân cách tùy chỉnh. Apache Commons CSV ở cấp thấp hơn nhưng nhanh hơn trên tệp lớn. Đối với trường hợp đơn giản (1-2 cột), parsing thủ công qua String.split(",") với xử lý thoát là đủ. Đối với dự án sản xuất có tệp CSV lớn, OpenCSV được khuyến nghị.

Protobuf và parsing luồng

Protocol Buffers của Google là định dạng tuần tự hóa nhị phân vượt trội hơn JSON về tốc độ và độ nhỏ gọn. Một thông điệp Protobuf chiếm ít không gian hơn 3-6 lần so với JSON tương đương và phân tích nhanh hơn 4-10 lần nhờ định dạng nhị phân và lược đồ cứng nhắc. Nhược điểm chính là thiếu khả năng đọc của con người và cần tạo mã từ tệp .proto qua trình biên dịch protoc.

Parsing luồng Protobuf được triển khai qua CodedInputStream — máy khách đọc các trường khi chúng đến mà không tải toàn bộ thông điệp. Mỗi trường có một thẻ (số + kiểu) và trình phân tích có thể bỏ qua các trường không xác định. Theo Google (2026), parsing luồng Protobuf tiêu thụ ít hơn tới 90% bộ nhớ khi xử lý thông điệp từ 1 MB, rất quan trọng cho thiết bị di động với RAM hạn chế. Protobuf-lite là phiên bản đặc biệt cho Android, tối ưu hóa kích thước mã được tạo.

Câu hỏi thường gặp

JSONSerialization khác JSONDecoder như thế nào?

JSONSerialization là parsing thủ công trả về Any (Dictionary, Array) mà không định kiểu. JSONDecoder là giải tuần tự hóa tự động thành kiểu Codable. JSONSerialization cung cấp tính linh hoạt cho cấu trúc động, trong khi JSONDecoder cung cấp tốc độ và an toàn kiểu cho lược đồ đã biết. Trong sản xuất, JSONDecoder được khuyến nghị.

Khi nào nên sử dụng parsing luồng thay vì tải toàn bộ tài liệu?

Parsing luồng là bắt buộc đối với phản hồi trên 500 KB, khi phân tích nguồn cấp RSS/Atom và khi xử lý tệp trên thiết bị có bộ nhớ hạn chế. Đối với phản hồi API điển hình đến 100 KB, giải tuần tự hóa tự động qua JSONDecoder hoặc Moshi tốt hơn — mã sạch hơn và phát triển nhanh hơn.

Định dạng dữ liệu nào được hỗ trợ trong Android SDK mặc định?

Android SDK bao gồm org.json (JSONObject, JSONArray), XmlPullParser (XML) và android.util.JsonReader. CSV, YAML và Protobuf yêu cầu thư viện bổ sung: OpenCSV cho CSV, SnakeYAML cho YAML, protobuf-javalite cho Protobuf.

Làm gì khi nhận JSON không hợp lệ từ máy chủ?

Sử dụng chế độ lenient trong kotlinx.serialization hoặc JsonReader.setLenient(true) trong Moshi — nó bỏ qua dấu phẩy cuối, dấu ngoặc kép không được thoát và chú thích một dòng. Để xác thực đầy đủ, hãy triển khai kiểm thử hợp đồng qua Pact hoặc Spring Cloud Contract.

Parsing SAX là gì và được sử dụng ở đâu?

SAX (Simple API for XML) là trình phân tích XML luồng tạo ra các sự kiện startElement, characters, endElement khi duyệt tài liệu. Nó được triển khai qua XmlPullParser trên Android và XMLParser trên iOS. Nó được sử dụng trong trình đọc RSS, đồng bộ dữ liệu ngoại tuyến và xử lý tệp SVG.

Tổng kết

  • Parsing — thao tác cơ bản để xử lý dữ liệu có cấu trúc, rộng hơn giải tuần tự hóa: có thể theo luồng và không yêu cầu định kiểu.
  • JSON — định dạng chính cho REST API trong phát triển di động; được hỗ trợ bởi JSONSerialization (iOS) và org.json (Android).
  • Parsing luồng qua JsonReader, XmlPullParser và SAX tiết kiệm bộ nhớ và rất quan trọng cho tài liệu lớn.
  • Protobuf — định dạng nhanh nhất và nhỏ gọn nhất, được khuyến nghị cho hệ thống tải cao và đa nền tảng.
  • XmlPullParser trên Android và XMLParser trên iOS — công cụ parsing XML luồng tiêu chuẩn với mô hình dựa trên sự kiện.
  • Trình phân tích CSV (OpenCSV, Apache Commons CSV) hữu ích cho xuất báo cáo và tải dữ liệu tham chiếu.
  • Lựa chọn giữa parsing thủ công và tự động phụ thuộc vào kích thước dữ liệu, tính biến đổi của lược đồyêu cầu bộ nhớ của thiết bị.

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm