Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

วิธี Deserialize JSON เป็น .NET Object และดึงค่าเฉพาะจาก Array ด้วย Newtonsoft.Json

ใช้ 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
});