Chuyển JSON sang class C# có thuộc tính PascalCase và tên JSON gốc
Công cụ JSON to C# đọc một mẫu JSON (phản hồi API, file cấu hình, dữ liệu xuất từ hệ thống khác) và sinh ra các class hoặc record C# tương ứng. Mỗi khóa thành một thuộc tính đặt tên theo PascalCase, kèm [JsonPropertyName] của System.Text.Json hoặc [JsonProperty] của Newtonsoft.Json để giữ đúng tên khóa gốc. Kiểu dữ liệu được suy từ toàn bộ mẫu chứ không chỉ phần tử đầu tiên, có đánh dấu nullable, chọn List<T> hoặc mảng T[], đặt namespace, rồi sao chép hoặc tải về file .cs.
Tính năng nổi bật
- Sinh class với thuộc tính { get; set; } hoặc record positional của C# 9, thuộc tính dùng [property: ...] để gắn tên JSON đúng chỗ
- Gắn [JsonPropertyName] (System.Text.Json), [JsonProperty] (Newtonsoft.Json) hoặc không gắn; tùy chọn chỉ gắn khi tên thuộc tính khác khóa gốc
- Đổi khóa snake_case, kebab-case, có dấu tiếng Việt, có khoảng trắng hoặc bắt đầu bằng chữ số thành tên PascalCase hợp lệ; tránh trùng tên lớp chứa nó và các thành viên có sẵn như ToString, Equals
- Bật nullable reference types: thêm #nullable enable, đánh dấu string?, Order? cho trường có thể rỗng; trường bắt buộc kiểu tham chiếu được khởi tạo string.Empty hoặc new() để không bị cảnh báo CS8618
- Gộp mọi phần tử của mảng object thành một lớp: khóa vắng ở một số phần tử hoặc có giá trị null được đánh dấu nullable kèm chú thích
- Phân biệt số nguyên và số thực theo đúng chữ số trong JSON (1.0 vẫn là số thực), int tự lên long khi vượt 2.147.483.647, số vượt phạm vi long ra decimal; tùy chọn luôn dùng long và dùng decimal cho số thực
- Nhận diện chuỗi ngày giờ ISO 8601: có múi giờ ra DateTimeOffset, không có múi giờ ra DateTime
- Chọn List<T> hoặc T[], object rỗng ra Dictionary<string, object?>, mảng rỗng ra List<object?>, mảng lẫn kiểu ra object kèm chú thích các loại đã gặp
- Lớp con đặt tên theo khóa, phần tử mảng đổi sang số ít (orders thành Order, addresses thành Address), trùng tên thì ghép tên lớp cha
- Namespace kiểu file của C# 10 hoặc khối namespace { } cho dự án cũ; dòng chú thích gợi ý câu lệnh Deserialize đúng kiểu gốc, kể cả khi JSON gốc là mảng
- Mã cập nhật ngay khi gõ hoặc đổi tùy chọn; mở file .json từ máy, sao chép mã hoặc tải file .cs đặt theo tên lớp gốc; mọi thứ chạy trên trình duyệt
Vì sao không nên gõ tay model C# từ JSON
Một phản hồi API thực tế thường có vài chục khóa, lồng ba bốn tầng và có mảng object mà mỗi phần tử thiếu một vài trường. Gõ tay lớp C# cho cấu trúc đó dễ sai ở những chỗ khó thấy: gõ nhầm một chữ trong tên khóa làm thuộc tính luôn rỗng mà không báo lỗi, khai báo int cho trường có lúc mang số lẻ làm JsonException bật ra ở môi trường thật, hoặc quên đánh dấu nullable cho trường chỉ xuất hiện ở vài bản ghi. Công cụ này quét toàn bộ mẫu bạn dán vào, gộp các phần tử của mảng lại để thấy trường nào luôn có, trường nào lúc có lúc không, rồi sinh mã đúng quy ước đặt tên của C# mà vẫn giữ tên JSON gốc qua thuộc tính. Bạn chỉ còn việc rà lại vài chỗ được chú thích sẵn trong mã, thay vì dò từng khóa bằng mắt.
Lợi ích khi sử dụng
- Suy kiểu từ mọi phần tử của mảng, không bỏ sót trường chỉ có ở phần tử thứ hai trở đi như cách lấy mẫu phần tử đầu
- Tên thuộc tính đúng quy ước .NET mà vẫn khớp khóa snake_case hoặc camelCase của API nhờ thuộc tính tên JSON
- Mã sinh ra không kéo theo thư viện lạ: chỉ System, System.Collections.Generic và thư viện JSON bạn chọn
- Không gửi JSON lên máy chủ nào, phù hợp khi mẫu chứa dữ liệu khách hàng hoặc token nội bộ
- Đánh dấu sẵn chỗ cần quyết định bằng tay (trường chỉ có null, mảng lẫn kiểu, số quá lớn) thay vì đoán bừa
- Dùng cùng cách suy kiểu với các công cụ JSON sang Java, PHP, Kotlin trên trang, tiện khi một API có nhiều nhóm client
Cách chuyển JSON sang class C#
- 1Trong khối Tùy chọn mã C#, nhập Tên lớp gốc (mặc định Root) và Namespace, để trống namespace nếu không cần.
- 2Chọn Kiểu khai báo là class { get; set; } hoặc record (C# 9), chọn Thư viện JSON là System.Text.Json, Newtonsoft.Json hoặc Không gắn, chọn Kiểu mảng là List<T> hoặc T[].
- 3Bật hoặc tắt các ô: Luôn gắn tên JSON, Nullable reference types, Namespace kiểu file (C# 10+), Số nguyên luôn dùng long, Số thực dùng decimal, Nhận diện ngày giờ ISO 8601.
- 4Dán JSON vào ô JSON đầu vào, bấm Mở file .json để lấy file từ máy, hoặc bấm Nạp ví dụ để xem thử. JSON sai cú pháp sẽ báo lỗi kèm số dòng.
- 5Xem mã ở ô Mã C# sinh ra; mã đổi ngay khi bạn sửa JSON hoặc đổi tùy chọn. Đọc các dòng chú thích // để biết trường nào cần sửa kiểu bằng tay.
- 6Bấm Sao chép mã để dán vào Visual Studio, Rider hoặc VS Code, hoặc bấm Tải để lưu file .cs mang tên lớp gốc.
System.Text.Json hay Newtonsoft.Json: chọn thuộc tính nào
System.Text.Json nằm sẵn trong .NET từ bản Core 3.0, nhanh và là lựa chọn mặc định của ASP.NET Core. Thuộc tính đổi tên của nó là [JsonPropertyName("user_id")] trong namespace System.Text.Json.Serialization. Điểm cần nhớ: khi tự gọi JsonSerializer.Deserialize với tùy chọn mặc định, việc khớp tên phân biệt hoa thường, nên thuộc tính UserId không tự nhận khóa userId hay user_id. ASP.NET Core thì dùng bộ tùy chọn Web (camelCase, không phân biệt hoa thường) cho body của request, nên cùng một lớp có thể chạy đúng trong controller mà lại rỗng trong một đoạn code đọc file. Gắn tên JSON cho mọi thuộc tính, như công cụ làm mặc định, loại bỏ hẳn sự khác biệt đó. Newtonsoft.Json (Json.NET) vẫn phổ biến trong dự án .NET Framework và dự án cũ; thuộc tính tương ứng là [JsonProperty("user_id")] trong namespace Newtonsoft.Json. Thư viện này khớp tên không phân biệt hoa thường, nhưng khóa có gạch dưới vẫn cần thuộc tính. Nếu bạn cấu hình naming policy riêng cho toàn dự án, có thể chọn Không gắn để mã gọn hơn.
class với { get; set; } khác record positional thế nào
Lớp thường với thuộc tính { get; set; } chạy được trên mọi phiên bản C# và mọi thư viện JSON, dễ sửa dần từng thuộc tính, phù hợp với model dùng chung cho Entity Framework hoặc binding form. Record positional, có từ C# 9 (.NET 5), khai báo toàn bộ trường trong một dòng tham số và cho sẵn so sánh theo giá trị, ToString đọc được, cú pháp with để tạo bản sao đổi một vài trường. Với record positional, thuộc tính tên JSON phải viết dạng [property: JsonPropertyName("...")] để gắn vào thuộc tính sinh ra chứ không phải vào tham số hàm khởi tạo; công cụ đã sinh đúng dạng này. System.Text.Json từ .NET 5 đọc được record qua hàm khởi tạo có tham số, Newtonsoft.Json cũng khớp tham số theo tên. Record hợp với dữ liệu chỉ đọc như phản hồi API, DTO giữa các tầng; class hợp hơn khi bạn cần gán lại giá trị sau khi đọc.
Nullable reference types và cảnh báo CS8618
Từ C# 8, khi bật nullable reference types, string và các lớp được coi là không bao giờ null trừ khi khai báo string?. Trình biên dịch sẽ cảnh báo CS8618 cho thuộc tính không nullable chưa được gán giá trị khi thoát hàm khởi tạo. Để tránh hàng loạt cảnh báo đó, công cụ khởi tạo chuỗi bắt buộc bằng string.Empty, danh sách và lớp con bằng new() (cú pháp new có kiểu đích của C# 9), mảng bằng Array.Empty<T>(). Trường có thể rỗng, tức là có giá trị null trong mẫu hoặc vắng ở một số phần tử, được khai báo kèm dấu hỏi và không khởi tạo. Kiểu giá trị như int, bool, double, DateTimeOffset luôn có dấu hỏi khi có thể rỗng, kể cả khi tắt nullable reference types, vì đó là Nullable<T> có từ rất lâu. Nếu dự án còn ở C# 7.3 (.NET Framework), hãy tắt tùy chọn này: mã sẽ không có #nullable enable, không có dấu hỏi cho kiểu tham chiếu và không có phần khởi tạo cần C# 9.
Công cụ suy kiểu số, chuỗi ngày giờ và mảng ra sao
JSON chỉ có một loại số, nên công cụ đọc lại đúng chữ số trong văn bản: có dấu chấm hoặc số mũ là số thực (double, hoặc decimal nếu bạn bật), không có là số nguyên. Nhờ vậy giá trị viết 1.0 vẫn được coi là số thực, điều mà JSON.parse của JavaScript làm mất. Số nguyên nằm trong phạm vi -2.147.483.648 đến 2.147.483.647 ra int, vượt thì ra long, vượt cả long thì ra decimal kèm chú thích. Một trường có lúc là số nguyên, lúc là số lẻ ở các phần tử khác nhau sẽ ra số thực. Chuỗi khớp dạng ISO 8601 như 2024-05-27T07:32:00Z ra DateTimeOffset, chuỗi ngày giờ không có múi giờ hoặc chỉ có ngày ra DateTime; chỉ cần một mẫu không khớp là trường đó giữ string. Công cụ chỉ nhận dạng mà System.Text.Json đọc được: chữ T in hoa giữa ngày và giờ, múi giờ Z hoặc +07:00 có dấu hai chấm, ngày có thật trong lịch. Chuỗi như 2024-05-27 07:32:00 (dấu cách), +0700 hay 2024-02-30 được giữ string để chương trình không ném JsonException lúc chạy. Với mảng, công cụ dồn tất cả phần tử lại để suy kiểu phần tử: mảng rỗng ra List<object?>, mảng có phần tử null ra List<T?>, mảng lẫn số và chuỗi ra List<object?> kèm chú thích.
Mảng object có phần tử thiếu trường
API phân trang hay trả về danh sách mà mỗi bản ghi có tập khóa hơi khác nhau: bản ghi có ghi chú thì có note, không có thì bỏ hẳn khóa. Cách lấy phần tử đầu làm mẫu sẽ bỏ sót trường chỉ xuất hiện ở bản ghi sau, còn cách lấy giao các phần tử lại làm mất trường. Công cụ lấy hợp của tất cả khóa, đếm số lần mỗi khóa xuất hiện, rồi đánh dấu khóa không có ở mọi phần tử là có thể rỗng và ghi chú thích "không có ở mọi phần tử của mảng" ngay trên thuộc tính. Khi đọc bằng System.Text.Json hoặc Newtonsoft.Json, khóa vắng mặt sẽ để thuộc tính ở giá trị mặc định (null với kiểu có dấu hỏi), nên chương trình không lỗi. Muốn kết quả sát thực tế, hãy dán một mẫu có nhiều bản ghi đa dạng chứ đừng chỉ dán một bản ghi.
Đặt tên thuộc tính và lớp con
Tên khóa được tách thành từ theo gạch dưới, gạch ngang, khoảng trắng và chỗ chuyển chữ thường sang chữ hoa, dấu tiếng Việt được bỏ, rồi ghép lại theo PascalCase: user_id thành UserId, ngày_tạo thành NgayTao, HTTPStatus thành HttpStatus. Khóa bắt đầu bằng chữ số như 2fa được thêm tiền tố F. C# không cho thuộc tính trùng tên lớp chứa nó (lỗi CS0542), nên khóa root bên trong lớp Root thành RootValue; tên trùng các thành viên có sẵn như ToString, Equals, GetHashCode cũng được thêm hậu tố Value để không đè lên phương thức của object hay của record. Hai khóa khác nhau ra cùng một tên, chẳng hạn userId và user_id, sẽ được đánh số UserId và UserId2. Lớp con lấy tên theo khóa, phần tử của mảng đổi sang số ít bằng các luật tiếng Anh đơn giản; tên trùng kiểu có sẵn như List, Type, DateTime sẽ được đổi để không che mất kiểu thật.
Giới hạn cần biết
Công cụ suy kiểu từ mẫu, nên chỉ biết những gì có trong mẫu. Trường chỉ mang null ra object? và cần bạn sửa. Trường mang chuỗi số như "123" vẫn là string, vì đó đúng là kiểu trong JSON. Công cụ không sinh enum cho các giá trị chuỗi lặp lại, không gộp hai lớp con có cấu trúc giống nhau thành một, không sinh JsonConverter riêng cho trường đa hình. Khóa trùng lặp trong cùng một object được xử lý như JSON.parse: giá trị sau đè giá trị trước. Số nguyên vượt 2^53 được nhận đúng kiểu nhờ đọc chữ số gốc, nhưng nếu JSON từng đi qua JavaScript ở phía máy chủ thì chữ số cuối có thể đã sai từ trước; công cụ ghi chú thích khi gặp trường hợp này. Mã chưa được biên dịch thử trên trang, hãy build lại trong dự án sau khi dán.
Câu hỏi thường gặp (FAQ)
Dùng JSON to C# online thế nào để có class nhanh nhất?
Dán JSON vào ô JSON đầu vào, mã C# hiện ngay ở ô bên cạnh, rồi bấm Sao chép mã hoặc tải file .cs. Trước khi dán, hãy đặt Tên lớp gốc và Namespace theo dự án để không phải sửa sau. Nên dùng một phản hồi thật có nhiều bản ghi để kiểu được suy đủ.
Visual Studio đã có Paste JSON as Classes, công cụ này khác gì?
Lệnh Edit, Paste Special, Paste JSON As Classes của Visual Studio sinh lớp nhanh nhưng giữ nguyên tên khóa làm tên thuộc tính và không gắn thuộc tính tên JSON. Công cụ này đổi tên sang PascalCase kèm [JsonPropertyName] hoặc [JsonProperty], đánh dấu nullable theo toàn bộ mẫu, chọn được record và namespace kiểu file. Nó cũng dùng được trên máy không cài Visual Studio, ví dụ khi làm với VS Code hoặc Rider.
Nên chọn System.Text.Json hay Newtonsoft.Json?
Dự án .NET 5 trở lên, đặc biệt là ASP.NET Core, nên dùng System.Text.Json vì có sẵn và nhanh. Dự án .NET Framework hoặc đã dùng Json.NET từ trước thì chọn Newtonsoft.Json để thống nhất. Hai lựa chọn chỉ khác nhau ở dòng using và tên thuộc tính đổi tên, cấu trúc lớp giống hệt.
Vì sao thuộc tính vẫn null dù JSON có giá trị?
Lý do thường gặp nhất là tên không khớp: System.Text.Json mặc định phân biệt hoa thường và không tự đổi user_id thành UserId. Hãy giữ tùy chọn Luôn gắn tên JSON để mỗi thuộc tính có [JsonPropertyName] đúng khóa gốc. Nguyên nhân khác là thuộc tính không có setter công khai, điều không xảy ra với mã của công cụ.
Record trong mã sinh ra có đọc được bằng System.Text.Json không?
Được, System.Text.Json đọc record positional qua hàm khởi tạo có tham số từ .NET 5. Thuộc tính đổi tên phải gắn bằng [property: JsonPropertyName(...)], công cụ đã sinh đúng dạng này. Nếu dự án dưới .NET 5 hoặc dưới C# 9 thì hãy chọn class.
Khi nào nên bật Nullable reference types?
Bật khi dự án đã dùng nullable (mặc định với dự án .NET 6 trở lên tạo từ template). Khi đó trường có thể rỗng mang dấu hỏi và trình biên dịch nhắc bạn kiểm tra null trước khi dùng. Dự án cũ chưa bật nullable thì tắt tùy chọn để không sinh #nullable enable và phần khởi tạo cần C# 9.
Vì sao có trường bị khai báo object? kèm chú thích?
Trong mẫu, trường đó chỉ mang giá trị null, hoặc là mảng lẫn nhiều loại giá trị, nên không có cơ sở để chọn kiểu cụ thể. Hãy thay object? bằng kiểu thật theo tài liệu API. Nếu để nguyên, System.Text.Json sẽ trả về JsonElement cho trường đó.
Số tiền nên dùng double hay decimal?
Số tiền nên dùng decimal vì double là số dấu phẩy động nhị phân, cộng trừ nhiều lần sẽ lệch ở phần lẻ. Bật ô Số thực dùng decimal để mọi số thực trong mẫu ra decimal. Cả System.Text.Json và Newtonsoft.Json đều đọc số JSON vào decimal được.
Công cụ quyết định int hay long thế nào?
Nếu mọi giá trị nguyên của trường nằm trong phạm vi của int (đến 2.147.483.647) thì ra int, vượt thì ra long, vượt cả long thì ra decimal. Mã định danh hay dấu thời gian Unix tính bằng mili giây thường vượt int, nhưng mẫu của bạn có thể chỉ có số nhỏ. Bật Số nguyên luôn dùng long nếu bạn không chắc giá trị sau này sẽ lớn tới đâu.
Chuỗi ngày tháng có được đổi sang DateTime không?
Có, khi bật Nhận diện ngày giờ ISO 8601: chuỗi có múi giờ như 2024-05-27T07:32:00Z ra DateTimeOffset, chuỗi không có múi giờ hoặc chỉ có ngày ra DateTime. Dạng 27/05/2024, dạng có dấu cách thay chữ T hoặc múi giờ +0700 không có dấu hai chấm vẫn là string, vì System.Text.Json không đọc được các dạng đó vào DateTime. Chỉ cần một giá trị trong mẫu không khớp là trường đó giữ string.
JSON gốc là mảng thì dùng lớp sinh ra thế nào?
Khi JSON bắt đầu bằng dấu ngoặc vuông chứa các object, công cụ gộp các object thành lớp mang tên gốc và ghi chú thích gợi ý Deserialize<List<Root>>(json). Nếu mảng chứa số hay chuỗi, không có lớp nào được sinh, chú thích sẽ cho biết kiểu cần dùng, ví dụ List<int>.
Khóa JSON có dấu tiếng Việt hoặc khoảng trắng có sao không?
Không sao. Tên thuộc tính được bỏ dấu và ghép PascalCase, ví dụ "họ tên" thành HoTen, còn thuộc tính tên JSON giữ đúng chuỗi gốc có dấu nên vẫn khớp khi đọc. Ký tự đặc biệt trong khóa như ngoặc kép hay gạch chéo ngược được thoát đúng trong chuỗi C#.
Công cụ có sinh enum cho các giá trị lặp lại không?
Không. Trường như status với các giá trị "paid", "pending" vẫn ra string, vì công cụ không biết danh sách giá trị đầy đủ. Nếu muốn enum, bạn tự khai báo enum rồi gắn JsonStringEnumConverter (System.Text.Json) hoặc StringEnumConverter (Newtonsoft.Json).
Có class rồi, convert JSON string sang C# object thế nào?
Với System.Text.Json, gọi var root = JsonSerializer.Deserialize<Root>(json); với Newtonsoft.Json, gọi JsonConvert.DeserializeObject<Root>(json), trong đó json là chuỗi bạn nhận từ API hoặc đọc từ file. Dòng chú thích đầu mã sinh ra đã ghi sẵn câu lệnh đúng kiểu gốc, kể cả List<Root> khi JSON gốc là mảng. Chiều ngược lại, JsonSerializer.Serialize(root) hoặc JsonConvert.SerializeObject(root) cho lại chuỗi JSON với tên khóa gốc nhờ thuộc tính tên JSON.
JSON to C# khác gì JSON to TypeScript và JSON to Go Struct trên trang?
Ba công cụ cùng nhận một mẫu JSON nhưng sinh mã cho ba ngôn ngữ khác nhau: JSON to TypeScript ra interface cho phía frontend, JSON to Go Struct ra struct có thẻ json cho Go, còn trang này ra class hoặc record C# cho .NET. Phần riêng của C# là thuộc tính [JsonPropertyName] hay [JsonProperty], nullable reference types, chọn List<T> hay T[], DateTimeOffset và namespace. Nếu cùng một API có client .NET và Java hoặc Kotlin, các công cụ JSON to Java và JSON to Kotlin dùng chung cách suy kiểu với trang này nên kết quả khớp nhau.
Dữ liệu JSON có bị gửi đi đâu không?
Không. Việc đọc JSON và sinh mã đều chạy bằng JavaScript trên trình duyệt của bạn, trang không gửi nội dung ô nhập lên máy chủ. Dù vậy, với dữ liệu nhạy cảm bạn vẫn nên thay giá trị thật bằng giá trị mẫu, vì kiểu chỉ phụ thuộc vào dạng giá trị.
Có xử lý được file JSON lớn không?
File vài megabyte vẫn chạy được vì việc suy kiểu chỉ duyệt dữ liệu một lần. Tuy vậy mã cập nhật mỗi lần bạn gõ, nên với file rất lớn trình duyệt có thể chậm. Nên cắt bớt còn vài chục bản ghi đại diện, đủ để thấy mọi trường có thể xuất hiện.
Hai object con giống hệt nhau có được gộp thành một lớp không?
Không, mỗi khóa ra một lớp riêng, ví dụ billing_address và shipping_address ra BillingAddress và ShippingAddress dù cùng cấu trúc. Cách này an toàn khi hai nhánh sau này khác nhau. Nếu chắc chắn giống nhau, bạn có thể xóa một lớp và đổi kiểu thuộc tính sang lớp còn lại.
Mã sinh ra có cần chỉnh để chạy trên Unity hoặc .NET Framework không?
Với .NET Framework và Unity bản cũ, hãy chọn class, Newtonsoft.Json, tắt Nullable reference types và tắt Namespace kiểu file. JsonUtility của Unity không đọc thuộc tính { get; set; } mà cần trường công khai có [Serializable], nên nếu dùng JsonUtility bạn phải sửa thêm; dùng Newtonsoft.Json cho Unity thì không cần.
Từ khóa liên quan
- json to c#
- json to c# class
- json to c# model
- json to c# converter
- json to c# object
- json to c# class online
- json to c# online
- json to c# class converter
- json to c# object online
- json sang class c#
- chuyển json sang class c#
- json to c# record
- json to c# system.text.json
- json to c# newtonsoft
- jsonpropertyname generator
- paste json as classes
- tạo model c# từ json
- json to poco c#
- json to dto c#
- c# class generator from json
- deserialize json c# class
- json to c# nullable