Sinh data class Kotlin từ JSON cho kotlinx.serialization, Gson, Moshi
Công cụ JSON to Kotlin đọc một mẫu JSON và sinh các data class Kotlin tương ứng, sẵn annotation cho thư viện bạn dùng: @Serializable và @SerialName của kotlinx.serialization, @SerializedName của Gson, hoặc @Json và @JsonClass của Moshi. Khóa được đổi sang camelCase, trường có thể vắng hoặc null mang dấu ?, giá trị mặc định thêm theo lựa chọn để khóa vắng không làm hỏng việc đọc JSON. Hợp cho ứng dụng Android, Ktor và Spring dùng Kotlin.
Tính năng nổi bật
- Sinh data class với val hoặc var, mỗi object con thành một data class riêng đặt tên theo khóa, phần tử mảng đổi sang số ít (orders thành Order)
- kotlinx.serialization: @Serializable trên mọi lớp, @SerialName khi tên đổi; trường chưa rõ kiểu dùng JsonElement, object rỗng dùng JsonObject
- Gson: @SerializedName; Moshi: @Json(name = ...) kèm @JsonClass(generateAdapter = true) cho codegen; hoặc không gắn annotation
- Kiểu nullable với dấu ? cho trường có giá trị null hoặc vắng ở một số phần tử của mảng; phần tử mảng có null ra List<String?>
- Ba chế độ giá trị mặc định: không có, null cho trường nullable, hoặc cho mọi trường (0, 0L, 0.0, false, chuỗi rỗng, emptyList(), emptyMap())
- Cảnh báo khi dùng Gson mà lớp chưa có giá trị mặc định cho mọi tham số, vì khi đó Gson bỏ qua constructor và trường không null vẫn có thể nhận null
- Int tự lên Long khi giá trị vượt 2.147.483.647, số thực ra Double, 1.0 vẫn được hiểu là số thực nhờ đọc chữ số gốc; tùy chọn luôn dùng Long
- Khóa trùng từ khóa Kotlin như in, is, object, fun được bọc dấu backtick; chuỗi trong annotation thoát cả dấu $ để Kotlin không hiểu thành string template
- Mảng lẫn kiểu và trường chỉ có null được ghi chú thích để bạn sửa; khóa không có ở mọi phần tử cũng có chú thích
- Dòng chú thích gợi ý câu lệnh đọc JSON đúng thư viện: Json { ignoreUnknownKeys = true }.decodeFromString, Gson().fromJson với TypeToken khi gốc là mảng, Moshi adapter
- Cập nhật mã ngay khi gõ, mở file .json, sao chép, tải file .kt; chạy trên trình duyệt, không gửi dữ liệu đi
Data class Kotlin cho JSON: chỗ dễ sai nằm ở nullable
Kotlin phân biệt rõ kiểu có thể null và kiểu không null, và đó vừa là lợi thế vừa là nguồn lỗi khi đọc JSON. Khai báo val note: String cho một trường mà API có lúc bỏ hẳn, kotlinx.serialization sẽ ném MissingFieldException ngay khi gặp bản ghi thiếu, còn Gson thì lặng lẽ gán null vào trường không null và ứng dụng chỉ sập khi bạn dùng tới nó. Gõ tay data class cho phản hồi API dài vài chục khóa, rất khó nhớ hết trường nào luôn có. Công cụ quét toàn bộ mẫu, gộp các phần tử của mảng để biết khóa nào vắng ở đâu, rồi đánh dấu ? và thêm = null đúng chỗ. Phần annotation cũng được sinh theo thư viện bạn chọn, đổi thư viện chỉ cần bấm một nút.
Lợi ích khi sử dụng
- Đánh dấu nullable theo dữ liệu thật, giảm MissingFieldException và NullPointerException sau khi phát hành
- Đổi giữa kotlinx.serialization, Gson và Moshi trong một lần bấm khi dự án chuyển thư viện
- Không cần cài plugin cho IDE, dùng được trên máy bất kỳ, kể cả khi đang xem tài liệu API trên điện thoại
- Khóa snake_case, có dấu tiếng Việt, trùng từ khóa đều ra tên Kotlin hợp lệ kèm annotation giữ tên gốc
- JSON chứa token hay dữ liệu người dùng không rời khỏi trình duyệt
- Cùng cách suy kiểu với các công cụ JSON sang C#, Java, PHP trên trang, tiện khi backend và app dùng chung API
Cách chuyển JSON sang data class Kotlin
- 1Trong khối Tùy chọn mã Kotlin, nhập Tên lớp gốc và Package; để trống package nếu không cần.
- 2Chọn Thư viện JSON: kotlinx.serialization, Gson, Moshi hoặc Không gắn; đọc dòng ghi chú ngay bên dưới về yêu cầu của thư viện đó.
- 3Chọn Giá trị mặc định: Không có, null cho trường nullable, hoặc Cho mọi trường; bật tắt Luôn gắn tên JSON, Dùng var thay cho val, Số nguyên luôn dùng Long.
- 4Dán JSON vào ô JSON đầu vào, bấm Mở file .json hoặc Nạp ví dụ; JSON sai cú pháp sẽ báo lỗi kèm số dòng.
- 5Đọc mã ở ô Mã Kotlin sinh ra, chú ý các dòng chú thích // về trường cần sửa kiểu và câu lệnh đọc JSON.
- 6Bấm Sao chép mã hoặc Tải file .kt để đưa vào module model của dự án.
kotlinx.serialization: những điều cần biết khi dùng mã sinh ra
kotlinx.serialization làm việc lúc biên dịch, nên dự án cần plugin serialization trong Gradle (kotlin("plugin.serialization")) cùng thư viện kotlinx-serialization-json. Mỗi lớp cần @Serializable, công cụ đã gắn sẵn cho mọi lớp con. Hai hành vi mặc định hay gây bất ngờ: khóa có trong JSON mà không có trong lớp làm thư viện ném lỗi, nên câu lệnh gợi ý dùng Json { ignoreUnknownKeys = true }; và trường không có giá trị mặc định là bắt buộc, kể cả khi kiểu là String?, nên khóa vắng mặt sẽ ném MissingFieldException. Vì vậy chế độ mặc định của công cụ là thêm = null cho mọi trường nullable. Trường chưa rõ kiểu (chỉ có null trong mẫu, mảng lẫn số và chuỗi) dùng JsonElement thay vì Any, vì kotlinx.serialization không có serializer cho Any. Object rỗng dùng JsonObject, bạn đọc từng khóa bằng jsonObject["ten"].
Gson với data class Kotlin và vấn đề constructor
Gson được viết cho Java và không hiểu giá trị mặc định của Kotlin. Khi lớp có hàm khởi tạo không tham số, Gson gọi hàm đó rồi gán từng trường; khi không có, Gson tạo đối tượng mà không gọi constructor nào. Trường hợp thứ hai làm giá trị mặc định bị bỏ qua và trường khai báo không null vẫn có thể mang null nếu khóa vắng. Trên JVM, Kotlin chỉ sinh hàm khởi tạo không tham số cho data class khi mọi tham số đều có giá trị mặc định. Đó là lý do công cụ ghi chú thích cảnh báo khi bạn chọn Gson mà lớp còn tham số thiếu mặc định, và gợi ý chọn Giá trị mặc định cho mọi trường. Annotation @SerializedName đặt trước val trong constructor được Kotlin áp vào field, đúng chỗ Gson đọc. Nếu ứng dụng Android bật R8, hãy giữ tên các lớp model hoặc bật Luôn gắn tên JSON để mọi trường có @SerializedName.
Moshi: codegen hay reflection
Moshi có hai cách hỗ trợ Kotlin. Cách dùng reflection cần thêm KotlinJsonAdapterFactory vào Moshi.Builder và thư viện kotlin-reflect khá nặng. Cách codegen sinh adapter lúc biên dịch cho những lớp có @JsonClass(generateAdapter = true), cần KSP hoặc kapt cùng moshi-kotlin-codegen; công cụ gắn annotation này cho mọi lớp. Cả hai cách đều tôn trọng giá trị mặc định của Kotlin và báo lỗi khi trường không null nhận null, an toàn hơn Gson. Annotation đổi tên của Moshi là @Json(name = "user_id"). Với JSON gốc là mảng, bạn cần adapter cho kiểu có tham số, tạo bằng Types.newParameterizedType(List::class.java, Root::class.java).
Cách công cụ chọn kiểu
Mọi phần tử của một mảng object được gộp thành một data class: khóa có ở mọi phần tử và không bao giờ null là tham số không null, khóa vắng ở vài phần tử hoặc có lúc null mang dấu ?. Số được phân loại theo chữ số trong JSON: không có dấu chấm và số mũ là số nguyên, trong phạm vi Int thì ra Int, vượt thì ra Long; có phần lẻ ra Double; một trường lẫn cả hai ra Double. Mảng ra List, phần tử có null ra List<T?>, mảng rỗng ra List<JsonElement?> (kotlinx) hoặc List<Any?>. Lớp con lấy tên theo khóa, trùng tên thì ghép tên lớp cha; tên trùng kiểu dựng sẵn như List, Result, Pair cũng được đổi để không che kiểu thật. Chuỗi ngày giờ giữ String vì mỗi thư viện cần serializer hay adapter riêng cho kiểu thời gian.
val hay var, có nên thêm giá trị mặc định cho mọi trường
val làm data class bất biến: muốn đổi một trường thì dùng copy(note = "mới"), cách này an toàn khi đối tượng được chia sẻ giữa nhiều luồng hay giữa các màn hình. var chỉ cần khi một thư viện khác bắt buộc gán lại thuộc tính sau khi tạo, ví dụ một số ORM. Về giá trị mặc định, thêm cho mọi trường giúp đọc JSON không bao giờ lỗi vì thiếu khóa và giúp Gson có constructor không tham số, nhưng cũng làm mất tín hiệu khi API thật sự trả thiếu dữ liệu: bạn nhận về 0 hay chuỗi rỗng mà không biết. Với dữ liệu quan trọng như số tiền hay mã đơn hàng, nên để bắt buộc để lỗi lộ ra sớm. Lớp con không có giá trị rỗng hợp lý nên công cụ không thêm mặc định cho chúng, kể cả ở chế độ cho mọi trường.
Giới hạn
Công cụ suy kiểu từ mẫu nên chỉ biết những gì mẫu có: trường chỉ mang null cần bạn sửa kiểu, trường mang số dạng chuỗi như "123" vẫn là String. Công cụ không sinh enum class, sealed class cho dữ liệu đa hình, custom serializer cho ngày giờ, không gộp hai lớp có cùng cấu trúc. Số nguyên vượt phạm vi Long ra Double kèm chú thích vì kotlinx.serialization không có sẵn kiểu số lớn. Mã đã được kiểm thử cú pháp qua nhiều ca mẫu nhưng trang không chạy trình biên dịch Kotlin, hãy build lại trong dự án sau khi dán.
Câu hỏi thường gặp (FAQ)
Làm sao chuyển JSON sang Kotlin data class?
Dán JSON vào ô JSON đầu vào, data class hiện ngay ở ô kết quả, rồi bấm Sao chép mã hoặc tải file .kt. Chọn đúng thư viện JSON trước để annotation khớp với dự án. Dòng chú thích đầu kết quả ghi câu lệnh đọc JSON tương ứng.
Nên dùng kotlinx.serialization, Gson hay Moshi?
Dự án Kotlin mới, nhất là Kotlin Multiplatform hay Ktor, nên dùng kotlinx.serialization vì hiểu nullable và giá trị mặc định, không dùng reflection. Moshi cũng hiểu Kotlin tốt và phổ biến trên Android. Gson chỉ nên giữ cho dự án cũ đã dùng sẵn, vì nó không tôn trọng nullable của Kotlin.
Vì sao bị MissingFieldException khi đọc JSON bằng kotlinx.serialization?
Trường không có giá trị mặc định được coi là bắt buộc, kể cả khi kiểu có dấu ?. Khi JSON thiếu khóa đó, thư viện ném MissingFieldException. Chọn Giá trị mặc định là null cho trường nullable để mọi trường có dấu ? được thêm = null.
Gặp lỗi Encountered an unknown key thì sửa thế nào?
JSON có khóa không khai báo trong data class, và kotlinx.serialization mặc định báo lỗi. Tạo đối tượng Json { ignoreUnknownKeys = true } để bỏ qua khóa lạ, đúng như câu lệnh gợi ý trong kết quả. Nếu cần dùng khóa đó, hãy sinh lại lớp từ mẫu có khóa ấy.
Vì sao trường không null vẫn nhận null khi dùng Gson?
Khi data class không có hàm khởi tạo không tham số, Gson tạo đối tượng mà không gọi constructor, nên bỏ qua cả kiểm tra null lẫn giá trị mặc định của Kotlin. Kotlin chỉ sinh constructor không tham số khi mọi tham số có mặc định. Chọn Giá trị mặc định cho mọi trường, hoặc chuyển sang Moshi hay kotlinx.serialization.
@SerialName và @SerializedName khác nhau thế nào?
@SerialName thuộc kotlinx.serialization, @SerializedName thuộc Gson; cả hai đều khai báo tên khóa JSON cho một thuộc tính. Dùng nhầm annotation của thư viện này với thư viện kia thì sẽ không có tác dụng. Moshi dùng @Json(name = "...").
Trường JSON có tên trùng từ khóa Kotlin như in, object thì sao?
Công cụ giữ nguyên tên và bọc trong dấu backtick, ví dụ val `in`: Boolean. Kotlin cho phép cách đặt tên này và tên thuộc tính vẫn khớp khóa JSON. Bạn cũng có thể đổi sang tên khác rồi thêm annotation đổi tên.
Vì sao có trường kiểu JsonElement?
Với kotlinx.serialization, trường chỉ có null trong mẫu hoặc mảng lẫn nhiều loại giá trị không có kiểu cụ thể, mà thư viện không serialize được Any. JsonElement nhận mọi giá trị JSON để bạn tự đọc. Nếu biết kiểu thật từ tài liệu API, hãy thay JsonElement bằng kiểu đó.
Có tạo được data class cho Retrofit không?
Được. Retrofit dùng converter của Gson, Moshi hoặc kotlinx.serialization, nên bạn chọn thư viện trùng với converter đã cấu hình. Data class sinh ra dùng làm kiểu trả về của hàm trong interface API, ví dụ suspend fun getUser(): Root.
JSON gốc là mảng thì đọc thế nào?
Công cụ gộp các object của mảng thành lớp mang tên gốc. Với kotlinx.serialization đọc bằng decodeFromString<List<Root>>(json); với Gson cần TypeToken<List<Root>>; với Moshi cần Types.newParameterizedType. Câu lệnh tương ứng được ghi sẵn trong chú thích.
Khi nào số nguyên ra Long thay vì Int?
Khi có ít nhất một giá trị vượt phạm vi Int, tức lớn hơn 2.147.483.647 hoặc nhỏ hơn -2.147.483.648, ví dụ mã định danh lớn hay thời gian tính bằng mili giây. Mẫu nhỏ có thể chưa có giá trị lớn như vậy, nên nếu không chắc hãy bật Số nguyên luôn dùng Long.
Có nên dùng var thay cho val?
Thường không cần. val giữ data class bất biến, muốn đổi thì dùng copy(). Chỉ bật var khi thư viện hoặc framework khác yêu cầu gán lại thuộc tính sau khi tạo đối tượng.
Khóa snake_case có tự đổi sang camelCase không?
Có, user_id thành userId và được gắn annotation giữ khóa gốc. Chữ có dấu trong khóa được bỏ dấu ("ngày tạo" thành ngayTao), còn khóa mở đầu bằng chữ số như 2fa thành f2fa. Hai khóa ra cùng một tên sẽ được đánh số để không trùng.
Có sinh Kotlin POJO hay class thường thay cho data class không?
Không, công cụ JSON to Kotlin chỉ sinh data class, vì đó là cách viết model phổ biến trong Kotlin và có sẵn equals, hashCode, copy. Nếu cần lớp thường, bạn xóa chữ data ở đầu khai báo; constructor và thuộc tính giữ nguyên nên kotlinx.serialization, Gson, Moshi vẫn đọc được. Cần POJO Java có getter, setter thì dùng công cụ JSON to Java trên trang.
JSON to Kotlin khác gì JSON to Java và JSON to TypeScript trên trang?
Cùng cách suy kiểu từ mẫu, nhưng mỗi trang sinh mã cho một ngôn ngữ. Trang JSON to Kotlin có thứ riêng của Kotlin: kiểu nullable bằng dấu ?, giá trị mặc định trong constructor, @SerialName của kotlinx.serialization, @Json của Moshi, thoát dấu $ trong chuỗi. App Android viết bằng Java hoặc backend Spring dùng JSON to Java, còn frontend dùng JSON to TypeScript.
Khác gì plugin JSON To Kotlin Class trong Android Studio?
Plugin chạy trong IDE và có nhiều tùy chọn, nhưng phải cài vào từng máy. Công cụ này chạy trên trình duyệt, không cần cài, gộp schema từ mọi phần tử mảng để đánh dấu nullable và cảnh báo trường hợp Gson bỏ qua constructor. Bạn có thể dùng cả hai tùy hoàn cảnh.
Dữ liệu JSON có bị gửi đi không?
Không. Việc phân tích và sinh mã chạy hoàn toàn trên trình duyệt, trang không gửi hay lưu nội dung bạn dán. Đóng tab là dữ liệu mất.
Chuỗi ngày giờ có được đổi sang Instant hay LocalDateTime không?
Không, công cụ giữ String. kotlinx.serialization cần serializer riêng hoặc thư viện kotlinx-datetime, Gson và Moshi cần adapter riêng cho kiểu thời gian. Khi dự án đã có những thứ đó, bạn đổi kiểu trường bằng tay.
Mã sinh ra có biên dịch được ngay không?
Mã đã xử lý các ca dễ lỗi như từ khóa làm tên, dấu $ trong chuỗi annotation, dấu phẩy cuối danh sách tham số (hợp lệ từ Kotlin 1.4). Trang không có trình biên dịch Kotlin, nên hãy build lại trong dự án. Lỗi thường gặp sau khi dán là thiếu plugin serialization hoặc thiếu thư viện trong Gradle.
Từ khóa liên quan
- json to kotlin data class
- json to kotlin
- json to kotlin model
- json to kotlin data class converter
- json to kotlin pojo
- json to kotlin class
- json to kotlin converter
- json to kotlin data class online
- json to kotlin object
- json to kotlin data
- json sang data class kotlin
- chuyển json sang kotlin
- json to kotlin serialization
- json to kotlin gson
- json to kotlin moshi
- kotlin serialname generator
- json to data class android
- tạo data class kotlin từ json
- json to kotlin retrofit
- kotlinx serialization data class
- json to kotlin nullable
- json to kotlin online