Hướng dẫn lập trình với JSON bằng C++ với thư viện RapidJSON, các thao tác cơ bản như đọc, xử lý các dữ liệu trong JSON. Bài viết không giải quyết hết tất cả trường hợp nhưng đã đề xuất 1 thư viện gọn nhẹ để xử lý JSON trong C++.
Data Structure & Algorithm C/C++ Trần Thị Thu Hiền 2017-07-12 20:15:25

Giới thiệu

JSON là một định dạng được sử dụng khá phổ biến hiện nay trong việc lưu trữ và trao đổi dữ liệu giữa các thành phần trong dự án. Việc sử dụng file JSON giúp chuẩn hóa cấu trúc của dữ liệu mà không cần quan tâm nhiều đến sự khác biệt giữa các ngôn ngữ lập trình. Trong C++ để đọc hay ghi dữ liệu vào file định dạng JSON lập trình viên có thể sử dụng nhiều phương pháp khác nhau như xử lý chuỗi thuần túy hoặc sử dụng một số thư viện, phần mềm hỗ trợ như: JSONKit, JSONBox, RapidJSON,... Bài viết này nhằm giới thiệu đến bạn đọc một số khái niệm về định dạng JSON và cách sử dụng RapidJSON để thao tác với định dạng JSON trong các dự án C++.

Tiền đề bài viết

Bài viết là một trong các tài liệu tham khảo cho các học viên STDIO Training trong khóa học C++ Căn Bản đến Nâng Cao. Ngoài ra bài viết có thêm mục đích làm phong phú nguồn tài liệu tham khảo cho cộng đồng.

Đối tượng hướng đến

Các đối tượng đang tìm kiếm 1 thư viện gọn nhẹ để xử lý JSON trong C++.

Giới thiệu JSON

JSON (JavaScript Object Noattion) JSON là một định dạng được sử dụng khá phổ biến hiện nay trong việc lưu trữ và trao đổi dữ liệu giữa các thành phần trong dự án. JSON được định nghĩa dựa theo cấu trúc gồm tập hợp các phần tử, mỗi phần tử mang cặp giá trị key-value. Các value có thể là một số nguyên, số thập phân, chuỗi ký tự, mảng giá trị hay một phần tử con.

{
    "id"         : 1,
    "name"       : "circle",
    "radius"     : 3.5,
    "array"      : [1, 5, 6, 8],
    "pos"        : {
                       "x" : 1.0,
                       "y" : 2.5
                   },
    "note" : null
}

Xử lý File JSON trong C++ bằng RapidJSON

Cách tích hợp vào chương trình

Download thư viện tại đây và copy vào thư mục project của bạn. Sau đó khai báo thư viện bạn cần sử dụng vào, ở bài viết này để phân tích và lấy dữ liệu từ JSON tôi sử dụng document.h:

#include "rapidjson/document.h"

using namespace rapidjson;

Một số hàm cơ bản

Để phân tích một chuỗi kí tự có định dạng JSON và truy vấn dữ liệu bên trong nó, đầu tiên bạn cần tạo 1 đối tượng Document và đưa chuỗi cần phân tích vào Document theo cú pháp sau:

const char* json = "{\"project\":\"stdio_demo\",\"id\":12}";
Document d;
d.Parse(json);

Sau bước này d sẽ chứa toàn bộ thông tin về các phần tử trong chuỗi JSON ban đầu, để truy cập đến các phần tử mong muốn ta gọi theo cú pháp d["<key của phần tử đó>"]. Ta có thể sử dụng tham chiếu để truy vấn nhanh đến các key như minh họa dưới đây:

Value &a = d["project"];

Lấy giá trị

Để truy vấn giá trị của phần tử với từ khóa tương ứng ta sử dụng hàm Get[Kiểu dữ liệu]. Ví dụ: GetString() với giá trị kiểu chuỗi, GetInt() với giá trị là số nguyên, GetDouble() với giá trị là số thập phân, GetArray() với giá trị là một mảng, GetObject() với giá trị là một đối tượng JSON...

d["project"].GetString()

Kiểm tra hợp lệ

Vì các giá trị có thể mang các kiểu dữ liệu khác nhau để tránh xảy ra lỗi khi truy vấn giá trị, RapidJSON hỗ trợ một số hàm sau:

HasMember("<key>"): trả về true nếu tồn tại key đó trong đối tượng JSON đang xét, ví dụ:

d.HasMember("project") // trả về giá trị true

IsInt(): trả về true nếu giá trị của phần tử là số nguyên

d["project"].IsInt() // trả về giá trị false

IsString(): trả về true nếu giá trị của phần tử là chuỗi kí tự

d["project"].IsString() // trả về giá trị true

Lấy giá trị trong mảng

Để lấy giá trị của JSON dưới dạng mảng ta có thể sử dụng dòng lệnh for để truy cập đến từng phần tử trong mảng. Ví dụ để in tất cả giá trị của mảng ứng với key "array" ở trên, ta có thể sử dụng cú pháp sau:

const Value& array = d["array"];

for (SizeType i = 0; i < array.Size(); i++)
{
	cout << array[i].GetInt() << "\n";
}