ใช้ Newtonsoft.Json (Json.NET) สำหรับ Deserialize JSON เป็น Strongly-typed Objects และเข้าถึงข้อมูลใน Array
ตัวอย่าง: เรียก API และ Deserialize เป็น Array
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Threading.Tasks;
public class Post
{
public int UserId { get; set; }
public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
}
public class JsonClient
{
private readonly HttpClient _httpClient;
public JsonClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task GetPostsAsync()
{
string url = "https://jsonplaceholder.typicode.com/posts";
string json = await _httpClient.GetStringAsync(url);
// Deserialize JSON Array -> Post[]
Post[] posts = JsonConvert.DeserializeObject(json);
return posts;
}
}
// ใช้งาน
static async Task Main()
{
using var httpClient = new HttpClient();
var client = new JsonClient(httpClient);
Post[] posts = await client.GetPostsAsync();
// ดึงค่าเฉพาะจาก Array
if (posts.Length > 0)
{
Post firstPost = posts[0];
Console.WriteLine($"First Post Title: {firstPost.Title}");
Console.WriteLine($"First Post Body: {firstPost.Body}");
}
// LINQ Query
var user1Posts = posts.Where(p => p.UserId == 1).Take(3);
foreach (var post in user1Posts)
{
Console.WriteLine($"[{post.Id}] {post.Title}");
}
}
ผลลัพธ์ตัวอย่าง
First Post Title: sunt aut facere repellat provident occaecati excepturi optio reprehenderit
First Post Body: quia et suscipit...
[1] sunt aut facere repellat provident occaecati excepturi optio reprehenderit
[2] qui est esse
[3] ea molestias quasi exercitationem repellat qui ipsa sit aut
Deserialize แบบ Dynamic (ไม่ต้องสร้าง Class)
string json = await httpClient.GetStringAsync(url);
// 1. JArray (LINQ to JSON)
JArray array = JArray.Parse(json);
string firstTitle = array[0]["title"]?.ToString();
Console.WriteLine(firstTitle);
// 2. Dynamic (ExpandoObject)
dynamic posts = JsonConvert.DeserializeObject(json);
Console.WriteLine(posts[0].title);
// 3. Anonymous Type (Type Inference)
var anonPosts = JsonConvert.DeserializeAnonymousType(json, new[] { new { Id = 0, Title = "" } });
foreach (var p in anonPosts.Take(2))
Console.WriteLine($"{p.Id}: {p.Title}");
Deserialize เฉพาะ Fields ที่ต้องการ (Performance)
// ใช้ JsonSerializerSettings + ContractResolver
var settings = new JsonSerializerSettings
{
// แปลงเฉพาะ Properties ที่มี Attribute [JsonProperty] หรือ Public Properties
// สำหรับ Filter Fields: ใช้ Custom ContractResolver หรือ Select หลัง Deserialize
};
var posts = JsonConvert.DeserializeObject(json, settings);
// หรือ Select หลัง Deserialize (ง่ายกว่า)
var titles = posts.Select(p => p.Title).ToList();
Error Handling
try
{
Post[] posts = JsonConvert.DeserializeObject(json);
}
catch (JsonSerializationException ex)
{
Console.WriteLine($"JSON Format Error: {ex.Message}");
}
catch (JsonReaderException ex)
{
Console.WriteLine($"JSON Syntax Error: {ex.Message}");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Network Error: {ex.Message}");
}
Best Practices
- ใช้
HttpClientแบบ Singleton/Static (DI:IHttpClientFactory) - ตั้ง
TimeoutและDefaultRequestHeaders(User-Agent, Accept) - ใช้
ConfigureAwait(false)ใน Library Code - Enable
Nullable Reference Types(#nullable enable) สำหรับ Properties - พิจารณา
System.Text.Json(Built-in .NET Core 3.0+) สำหรับ Performance
System.Text.Json Equivalent (.NET Core 3.0+)
using System.Text.Json;
Post[] posts = await JsonSerializer.DeserializeAsync(await httpClient.GetStreamAsync(url));
// หรือ
Post[] posts = JsonSerializer.Deserialize(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true // Map "userId" -> UserId
});