CodeGym /Các khóa học /C# SELF /Sử dụng Newtonsoft.Json

Sử dụng Newtonsoft.Json

C# SELF
Mức độ, Bài học
Có sẵn

1. Giới thiệu

Newtonsoft.Json — về cơ bản là một "đồ già" theo nghĩa tốt. Nó từng là tiêu chuẩn de-facto để làm việc với JSON trong hệ sinh thái .NET suốt nhiều năm, ngay cả trước khi System.Text.Json xuất hiện. Hàng triệu project, hàng nghìn thư viện và framework (thậm chí nhiều phần của ASP.NET Core trước đây) dùng Json.NET.

Ưu điểm của nó là:

  • Chức năng phong phú và linh hoạt: Json.NET có vô số setting, attribute và khả năng tùy biến cho quá trình serialization/deserialization. Nó làm được nhiều thứ mà System.Text.Json làm khó hơn hoặc không làm được.
  • Khoan dung với JSON "không hoàn hảo": dữ liệu từ hệ thống bên ngoài không luôn sạch — Json.NET thường chịu đựng tốt hơn và cho phép deserialize mà ít đau hơn.
  • Tương thích ngược: nếu project hoặc thư viện của bạn phụ thuộc vào Json.NET thì vẫn cần biết dùng nó.

Tất nhiên, System.Text.Json nhanh hơn và được thiết kế theo yêu cầu hiện đại. Nhưng Newtonsoft.Json vẫn là một công cụ mạnh, đặc biệt khi bạn cần logic đặc thù hoặc tối đa tính linh hoạt.

Cách cài Newtonsoft.Json?

Vì đây là thư viện bên ngoài, thêm package qua NuGet:

  1. Mở dự án.
  2. Nhấp chuột phải vào project trong Solution Explorer.
  3. Chọn "Manage NuGet Packages...".
  4. Trong ô tìm kiếm nhập Newtonsoft.Json.
  5. Chọn package và nhấn "Install".

Sau khi cài xong sẽ có dependency mới — giờ có thể dùng Json.NET!

So sánh khả năng của Newtonsoft.Json và System.Text.Json

Tính năng System.Text.Json Newtonsoft.Json
Serialize/deserialize đơn giản Có Có
Hỗ trợ attribute cho properties Một phần Đầy đủ
Custom converters Có Có
Làm việc với trường private Không Có
Làm việc với cấu trúc động Hạn chế Có
LINQ to JSON (JObject/JArray) Không Có
Reference Loop Handling Có Có
Hỗ trợ DataTable, DataSet và kiểu phức tạp Không Có
Hiệu năng Tốt hơn Ổn

2. Ví dụ serialize và deserialize đối tượng đơn giản

Lấy cấu trúc game chung mà ta sẽ phát triển dần trong các bài:

public class Player
{
    public string Name { get; set; }
    public int Health { get; set; }
    public bool IsAlive { get; set; }
    public List<string> Inventory { get; set; }
    public Position Position { get; set; }
}

public class Position
{
    public int X { get; set; }
    public int Y { get; set; }
}

Bây giờ lưu đối tượng Player thành JSON và khôi phục lại:

using Newtonsoft.Json;

Player player1 = new Player
{
    Name = "Aragorn",
    Health = 100,
    IsAlive = true,
    Inventory = new List<string> { "sword", "bow", "healing potion" },
    Position = new Position { X = 10, Y = 25 }
};

// Serial hóa thành chuỗi JSON
string json = JsonConvert.SerializeObject(player1, Formatting.Indented);
Console.WriteLine(json);

// Deserialize trả về object Player
Player player2 = JsonConvert.DeserializeObject<Player>(json);
Console.WriteLine($"Tên: {player2.Name}, sức khỏe: {player2.Health}");

Xong? Gần rồi, nhưng đó chỉ là phần nổi của tảng băng. Ta sẽ xem vì sao Newtonsoft.Json thú vị và linh hoạt hơn các thư viện khác.

3. Format, cài đặt và tham số nâng cao

Khi serial hóa object, bạn có thể lấy chuỗi gọn nhẹ hoặc JSON đẹp, nhiều lựa chọn do các setting điều khiển.

Ví dụ: Các kiểu format khác nhau

// JSON dễ đọc đẹp
string prettyJson = JsonConvert.SerializeObject(player1, Formatting.Indented);

// JSON "minified" gọn nhẹ
string compactJson = JsonConvert.SerializeObject(player1, Formatting.None);

Cấu hình serialize

Nếu cần, truyền JsonSerializerSettings để tinh chỉnh:

var settings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore, // Bỏ qua các trường có giá trị null
    DefaultValueHandling = DefaultValueHandling.Ignore, // Bỏ qua các trường có giá trị mặc định
    Formatting = Formatting.Indented
};
string customJson = JsonConvert.SerializeObject(player1, settings);

Bạn có toàn quyền kiểm soát đầu ra: muốn bỏ field rỗng thì có thể, cần serialize cả property private thì cấu hình contract.

4. Điều khiển fields và properties bằng attribute

Newtonsoft.Json hỗ trợ hệ thống attribute mạnh mẽ để tinh chỉnh serialization ngay trong class.

JsonProperty — Đổi tên property

Nếu protocol JSON yêu cầu tên field khác:

public class Player
{
    [JsonProperty("player_name")]
    public string Name { get; set; }
    // ...
}

JSON kết quả:

{ "player_name": "Aragorn", ... }

JsonIgnore — Bỏ qua property

public class Player
{
    [JsonIgnore]
    public int Health { get; set; }
}

Bây giờ trường Health sẽ biến mất khi serialize.

JsonConverter — Chuyển đổi tuỳ chỉnh

Cho phép chỉ định converter để xử lý một field cụ thể.

public class Player
{
    [JsonConverter(typeof(InventoryToStringConverter))]
    public List<string> Inventory { get; set; }
}

(Chi tiết về converters — ở phần dưới.)

5. Làm việc với object lồng nhau và collection

Json.NET xử lý tốt object lồng nhau, mảng, collection, dictionary.

Ví dụ: Dictionary

public class GameStats
{
    public Dictionary<string, int> Scores { get; set; }
}

GameStats stats = new GameStats
{
    Scores = new Dictionary<string, int>
    {
        ["Alice"] = 1023,
        ["Bob"] = 999
    }
};

string statsJson = JsonConvert.SerializeObject(stats, Formatting.Indented);
Console.WriteLine(statsJson);

JSON sẽ trông như sau:

{
  "Scores": {
    "Alice": 1023,
    "Bob": 999
  }
}

6. Cấu trúc phức tạp: liên kết vòng, Self-Referencing Objects

Đôi khi object tham chiếu lẫn nhau. Newtonsoft.Json hỗ trợ serialize những cấu trúc như vậy bằng các setting đặc biệt.

Ví dụ: Giải quyết vòng tham chiếu

public class Person
{
    public string Name { get; set; }
    public Person Parent { get; set; }
    public List<Person> Children { get; set; }
}

// Cấu hình serialize cho vòng tham chiếu
var settings = new JsonSerializerSettings
{
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore // hoặc .Serialize
};

Person p1 = new Person { Name = "Bố" };
Person p2 = new Person { Name = "Con", Parent = p1 };
p1.Children = new List<Person> { p2 };

string json = JsonConvert.SerializeObject(p1, settings);
Console.WriteLine(json);

Mặc định, nếu để ReferenceLoopHandling = Error, bạn sẽ nhận được exception. Cái này ngăn chặn việc serialize vô hạn.

7. Làm việc với cấu trúc động: JObject, JArray

Khi cấu trúc JSON không biết trước hoặc thay đổi linh hoạt, dùng object động thay vì kiểu tĩnh C#.

Các kiểu chính:

  • JObject — đại diện cho JSON object.
  • JArray — đại diện cho mảng.
using Newtonsoft.Json.Linq;

// Chuyển chuỗi thành JObject
string json = @"{ 'name': 'Aragorn', 'health': 100 }";
JObject obj = JObject.Parse(json);

Console.WriteLine((string)obj["name"]); // Aragorn
Console.WriteLine((int)obj["health"]);  // 100

// Thêm property động
obj["class"] = "Ranger";
Console.WriteLine(obj.ToString());

Duyệt mảng

string jsonArr = @"['apple', 'banana', 'cherry']";
JArray array = JArray.Parse(jsonArr);

foreach (JToken item in array)
{
    Console.WriteLine(item);
}

8. Hỗ trợ versioning và trường bắt buộc

Format JSON có thể thay đổi, field có thể mất. Dùng attribute và setting như sau:

  • [JsonProperty(Required = Required.Always)] — yêu cầu field phải có (nếu không sẽ ném exception).
  • [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] — gán giá trị mặc định nếu field không có.
public class Player
{
    [JsonProperty(Required = Required.Always)]
    public string Name { get; set; }

    [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
    [DefaultValue(50)]
    public int Health { get; set; }
}

9. Chuyển đổi ngày và format thời gian

Làm việc với ngày thường cần format rõ ràng.

var dateSettings = new JsonSerializerSettings
{
    DateFormatString = "yyyy-MM-dd"
};
string json = JsonConvert.SerializeObject(DateTime.Now, dateSettings);
Console.WriteLine(json); // "2024-06-15"

Và ngược lại khi deserialize:

string dateJson = "\"2024-06-15\""; // Lưu ý: đây là một chuỗi trong dấu ngoặc kép!
DateTime dt = JsonConvert.DeserializeObject<DateTime>(dateJson);
Console.WriteLine(dt);
2
Nhiệm vụ
C# SELF, mức độ, bài học
Đã khóa
Sử dụng các thuộc tính JsonProperty và JsonIgnore
Sử dụng các thuộc tính JsonProperty và JsonIgnore
1
Khảo sát/đố vui
, cấp độ , bài học
Không có sẵn
Các class chuẩn để serialize
Các class và thư viện để serialize
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION