์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ JSON.NET ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ JSON ๋งˆ์Šคํ„ฐํ•˜๊ธฐ: C# ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ์™„๋ฒฝ ๊ฐ€์ด๋“œ ๐Ÿš€

๐Ÿš€ JSON.NET ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ JSON ๋งˆ์Šคํ„ฐํ•˜๊ธฐ: C# ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ์™„๋ฒฝ ๊ฐ€์ด๋“œ ๐Ÿš€

C# ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ๊ผญ ์•Œ์•„์•ผ ํ•  JSON ์ฒ˜๋ฆฌ์˜ ๋ชจ๋“  ๊ฒƒ!

์•ˆ๋…•? ์˜ค๋Š˜์€ C# ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ๋ฐ˜๋“œ์‹œ ์•Œ์•„์•ผ ํ•  JSON.NET(Newtonsoft.Json) ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•ด ํ•จ๊ป˜ ์•Œ์•„๋ณผ ๊ฑฐ์•ผ. JSON์€ ํ˜„๋Œ€ ์›น ๊ฐœ๋ฐœ์—์„œ ๋ฐ์ดํ„ฐ ๊ตํ™˜ ํ˜•์‹์˜ ํ‘œ์ค€์ด ๋˜์—ˆ๊ณ , C#์—์„œ ์ด๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฐ€์žฅ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๊ฐ€ ๋ฐ”๋กœ JSON.NET์ด์ง€! ๐Ÿ˜Ž

์ด ๊ธ€์„ ํ†ตํ•ด JSON.NET์˜ ๊ธฐ๋ณธ๋ถ€ํ„ฐ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ๊นŒ์ง€ ๋ชจ๋‘ ๋งˆ์Šคํ„ฐํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ. ํŠนํžˆ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์„ ๊ฐœ๋ฐœํ•  ๋•Œ๋„ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„, ์„œ๋น„์Šค ์ •๋ณด, API ์‘๋‹ต ๋“ฑ์„ JSON์œผ๋กœ ์ฃผ๊ณ ๋ฐ›๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์œผ๋‹ˆ ์‹ค๋ฌด์— ๋ฐ”๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ง€์‹์ด ๋  ๊ฑฐ์•ผ! ๊ทธ๋Ÿผ ์‹œ์ž‘ํ•ด๋ณผ๊นŒ? ๐Ÿ

๐Ÿ“š ๋ชฉ์ฐจ

  1. JSON๊ณผ JSON.NET ์†Œ๊ฐœ
  2. JSON.NET ์„ค์น˜ ๋ฐ ๊ธฐ๋ณธ ์„ค์ •
  3. JSON ์ง๋ ฌํ™”(Serialization) ๋งˆ์Šคํ„ฐํ•˜๊ธฐ
  4. JSON ์—ญ์ง๋ ฌํ™”(Deserialization) ์™„๋ฒฝ ์ดํ•ด
  5. LINQ to JSON์œผ๋กœ ๋™์  ๋ฐ์ดํ„ฐ ๋‹ค๋ฃจ๊ธฐ
  6. JSON ์Šคํ‚ค๋งˆ ๊ฒ€์ฆํ•˜๊ธฐ
  7. ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ๋ฐ ์„ฑ๋Šฅ ์ตœ์ ํ™”
  8. ์‹ค์ „ ์˜ˆ์ œ: ์›น API์™€ JSON.NET
  9. JSON.NET vs System.Text.Json ๋น„๊ต
  10. ๋งˆ๋ฌด๋ฆฌ ๋ฐ ์ถ”๊ฐ€ ์ž๋ฃŒ

1. JSON๊ณผ JSON.NET ์†Œ๊ฐœ ๐ŸŒŸ

JSON(JavaScript Object Notation)์€ ๊ฒฝ๋Ÿ‰ ๋ฐ์ดํ„ฐ ๊ตํ™˜ ํ˜•์‹์œผ๋กœ, ์‚ฌ๋žŒ์ด ์ฝ๊ณ  ์“ฐ๊ธฐ ์‰ฝ๊ณ  ๊ธฐ๊ณ„๊ฐ€ ํŒŒ์‹ฑํ•˜๊ณ  ์ƒ์„ฑํ•˜๊ธฐ ์‰ฌ์šด ํ…์ŠคํŠธ ํ˜•์‹์ด์•ผ. ์›น API, ์„ค์ • ํŒŒ์ผ, ๋ฐ์ดํ„ฐ ์ €์žฅ ๋“ฑ ๋‹ค์–‘ํ•œ ์šฉ๋„๋กœ ์‚ฌ์šฉ๋˜์ง€. ๐Ÿค“

๊ฐ„๋‹จํ•œ JSON ์˜ˆ์‹œ:

{
  "name": "ํ™๊ธธ๋™",
  "age": 30,
  "isActive": true,
  "skills": ["C#", "ASP.NET", "JSON.NET"],
  "address": {
    "city": "์„œ์šธ",
    "zipCode": "12345"
  }
}

JSON.NET(Newtonsoft.Json)์€ James Newton-King์ด ๊ฐœ๋ฐœํ•œ .NET์šฉ JSON ํ”„๋ ˆ์ž„์›Œํฌ๋กœ, ํ˜„์žฌ ๊ฐ€์žฅ ์ธ๊ธฐ ์žˆ๊ณ  ๊ฐ•๋ ฅํ•œ JSON ์ฒ˜๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์•ผ. NuGet์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ๋‹ค์šด๋กœ๋“œ๋œ ํŒจํ‚ค์ง€ ์ค‘ ํ•˜๋‚˜์ด๊ธฐ๋„ ํ•ด! ๐Ÿ†

JSON.NET์˜ ์ฃผ์š” ํŠน์ง• โœจ

  1. ๊ฐ•๋ ฅํ•œ ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™” - ๋ณต์žกํ•œ .NET ๊ฐ์ฒด๋„ JSON์œผ๋กœ ์‰ฝ๊ฒŒ ๋ณ€ํ™˜
  2. LINQ to JSON - JSON ๋ฐ์ดํ„ฐ๋ฅผ LINQ๋กœ ์ฟผ๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ
  3. ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ - JSON ์Šคํ‚ค๋งˆ๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
  4. ๊ณ ์„ฑ๋Šฅ - ์ตœ์ ํ™”๋œ ์„ฑ๋Šฅ์œผ๋กœ ๋Œ€์šฉ๋Ÿ‰ JSON ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
  5. ์œ ์—ฐํ•œ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• - ๋‹ค์–‘ํ•œ ์„ค์ •๊ณผ ํ™•์žฅ ๊ฐ€๋Šฅ์„ฑ ์ œ๊ณต
JSON.NET์˜ ์ฃผ์š” ๊ธฐ๋Šฅ ์ง๋ ฌํ™” ๊ฐ์ฒด โ†’ JSON ์—ญ์ง๋ ฌํ™” JSON โ†’ ๊ฐ์ฒด JSON.NET Newtonsoft.Json LINQ to JSON ์ฟผ๋ฆฌ ๊ธฐ๋Šฅ ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ

์žฌ๋Šฅ๋„ท๊ณผ ๊ฐ™์€ ์„œ๋น„์Šค ํ”Œ๋žซํผ์„ ๊ฐœ๋ฐœํ•  ๋•Œ๋„ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„, ์„œ๋น„์Šค ๋ชฉ๋ก, ๊ฒฐ์ œ ์ •๋ณด ๋“ฑ์„ JSON ํ˜•ํƒœ๋กœ ์ฃผ๊ณ ๋ฐ›๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„. JSON.NET์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ์ด๋Ÿฐ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์ง€! ๐Ÿ‘

2. JSON.NET ์„ค์น˜ ๋ฐ ๊ธฐ๋ณธ ์„ค์ • ๐Ÿ”ง

JSON.NET์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋จผ์ € ํ”„๋กœ์ ํŠธ์— ์„ค์น˜ํ•ด์•ผ ํ•ด. ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ NuGet ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฑฐ์•ผ. ๐Ÿ˜‰

NuGet์œผ๋กœ ์„ค์น˜ํ•˜๊ธฐ ๐Ÿ“ฆ

๋ฐฉ๋ฒ• 1: ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ € ์ฝ˜์†” ์‚ฌ์šฉ

PM> Install-Package Newtonsoft.Json

๋ฐฉ๋ฒ• 2: .NET CLI ์‚ฌ์šฉ

dotnet add package Newtonsoft.Json

๋ฐฉ๋ฒ• 3: Visual Studio์˜ NuGet ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž UI ์‚ฌ์šฉ

1. ์†”๋ฃจ์…˜ ํƒ์ƒ‰๊ธฐ์—์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์šฐํด๋ฆญ
2. 'ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž' โ†’ 'NuGet ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ' ์„ ํƒ
3. ๊ฒ€์ƒ‰์ฐฝ์— 'Newtonsoft.Json' ์ž…๋ ฅ
4. ํŒจํ‚ค์ง€๋ฅผ ์„ ํƒํ•˜๊ณ  '์„ค์น˜' ๋ฒ„ํŠผ ํด๋ฆญ

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• ์‹œ์ž‘ํ•˜๊ธฐ ๐Ÿš€

์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์ฝ”๋“œ์—์„œ Newtonsoft.Json ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

// ์ด์ œ JSON.NET์˜ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด!

JSON.NET ๊ธฐ๋ณธ ์„ค์ • ์กฐ์ •ํ•˜๊ธฐ โš™๏ธ

JSON.NET์€ ๋‹ค์–‘ํ•œ ์„ค์ •์„ ํ†ตํ•ด ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™” ๋™์ž‘์„ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์–ด. ์ฃผ์š” ์„ค์ •์„ ์•Œ์•„๋ณด์ž:

// JsonSerializerSettings ๊ฐ์ฒด ์ƒ์„ฑ
var settings = new JsonSerializerSettings
{
    Formatting = Formatting.Indented,  // ๋“ค์—ฌ์“ฐ๊ธฐ ์ ์šฉ (์˜ˆ์˜๊ฒŒ ์ถœ๋ ฅ)
    NullValueHandling = NullValueHandling.Ignore,  // null ๊ฐ’ ๋ฌด์‹œ
    DateFormatHandling = DateFormatHandling.IsoDateFormat,  // ISO ๋‚ ์งœ ํ˜•์‹ ์‚ฌ์šฉ
    ContractResolver = new CamelCasePropertyNamesContractResolver()  // ์†์„ฑ๋ช… camelCase๋กœ ๋ณ€ํ™˜
};

// ์„ค์ • ์ ์šฉํ•˜์—ฌ ์ง๋ ฌํ™”
string json = JsonConvert.SerializeObject(myObject, settings);

์ฃผ์š” ์„ค์ • ์˜ต์…˜ ๐Ÿ› ๏ธ

์„ค์ • ์„ค๋ช… ์‚ฌ์šฉ ์˜ˆ
Formatting JSON ์ถœ๋ ฅ ํ˜•์‹ ์ง€์ • Formatting.Indented ๋˜๋Š” Formatting.None
NullValueHandling null ๊ฐ’ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ• NullValueHandling.Include ๋˜๋Š” NullValueHandling.Ignore
DefaultValueHandling ๊ธฐ๋ณธ๊ฐ’ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ• DefaultValueHandling.Include ๋˜๋Š” DefaultValueHandling.Ignore
ContractResolver ์†์„ฑ๋ช… ๋ณ€ํ™˜ ๊ทœ์น™ CamelCasePropertyNamesContractResolver
ReferenceLoopHandling ์ˆœํ™˜ ์ฐธ์กฐ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ• ReferenceLoopHandling.Ignore

์ด๋Ÿฐ ์„ค์ •๋“ค์€ ํ”„๋กœ์ ํŠธ ์ „์ฒด์— ์ ์šฉํ•˜๊ฑฐ๋‚˜ ํŠน์ • ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™” ์ž‘์—…์—๋งŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ์–ด. ํŠนํžˆ ์›น API๋ฅผ ๊ฐœ๋ฐœํ•  ๋•Œ ์‘๋‹ต ํ˜•์‹์„ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€ํ•˜๋ ค๋ฉด ์ „์—ญ ์„ค์ •์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„! ๐ŸŒ

๐Ÿ’ก ํ”„๋กœ ํŒ: ASP.NET Core์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด JSON.NET ์„ค์ •์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์–ด:

services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.Formatting = Formatting.Indented;
        options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
    });

3. JSON ์ง๋ ฌํ™”(Serialization) ๋งˆ์Šคํ„ฐํ•˜๊ธฐ ๐Ÿ“ค

์ง๋ ฌํ™”๋Š” C# ๊ฐ์ฒด๋ฅผ JSON ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์ด์•ผ. JSON.NET์€ ์ด ์ž‘์—…์„ ์ •๋ง ์‰ฝ๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ์ง€! ๐Ÿ™Œ

๊ธฐ๋ณธ ์ง๋ ฌํ™” ๋ฐฉ๋ฒ• ๐Ÿ“

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ์ง๋ ฌํ™” ๋ฐฉ๋ฒ•์€ JsonConvert.SerializeObject() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฑฐ์•ผ:

using Newtonsoft.Json;

// ์ง๋ ฌํ™”ํ•  ํด๋ž˜์Šค ์ •์˜
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public List<string> Hobbies { get; set; }
}

// ๊ฐ์ฒด ์ƒ์„ฑ
var person = new Person
{
    Name = "๊น€๊ฐœ๋ฐœ",
    Age = 28,
    Hobbies = new List<string> { "์ฝ”๋”ฉ", "๋…์„œ", "๊ฒŒ์ž„" }
};

// JSON์œผ๋กœ ์ง๋ ฌํ™”
string json = JsonConvert.SerializeObject(person);
Console.WriteLine(json);

// ์ถœ๋ ฅ: {"Name":"๊น€๊ฐœ๋ฐœ","Age":28,"Hobbies":["์ฝ”๋”ฉ","๋…์„œ","๊ฒŒ์ž„"]}

์˜ˆ์˜๊ฒŒ ๋“ค์—ฌ์“ฐ๊ธฐ๋œ JSON์„ ์›ํ•œ๋‹ค๋ฉด Formatting.Indented ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ผ:

string prettyJson = JsonConvert.SerializeObject(person, Formatting.Indented);
Console.WriteLine(prettyJson);

/* ์ถœ๋ ฅ:
{
  "Name": "๊น€๊ฐœ๋ฐœ",
  "Age": 28,
  "Hobbies": [
    "์ฝ”๋”ฉ",
    "๋…์„œ",
    "๊ฒŒ์ž„"
  ]
}
*/

์†์„ฑ ์ด๋ฆ„ ์ œ์–ดํ•˜๊ธฐ ๐Ÿท๏ธ

JSON ์†์„ฑ ์ด๋ฆ„์„ C# ์†์„ฑ ์ด๋ฆ„๊ณผ ๋‹ค๋ฅด๊ฒŒ ์ง€์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด [JsonProperty] ํŠน์„ฑ์„ ์‚ฌ์šฉํ•ด:

public class User
{
    [JsonProperty("user_name")]  // JSON์—์„œ๋Š” "user_name"์œผ๋กœ ํ‘œ์‹œ๋จ
    public string UserName { get; set; }
    
    [JsonProperty("email_address")]
    public string Email { get; set; }
    
    [JsonProperty("is_active")]
    public bool IsActive { get; set; }
}

์†์„ฑ ๋ฌด์‹œํ•˜๊ธฐ ๐Ÿ™ˆ

ํŠน์ • ์†์„ฑ์„ JSON์œผ๋กœ ์ง๋ ฌํ™”ํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด [JsonIgnore] ํŠน์„ฑ์„ ์‚ฌ์šฉํ•ด:

public class Customer
{
    public string Name { get; set; }
    
    public string Email { get; set; }
    
    [JsonIgnore]  // ์ด ์†์„ฑ์€ JSON์— ํฌํ•จ๋˜์ง€ ์•Š์Œ
    public string Password { get; set; }
    
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]  // null์ผ ๋•Œ๋งŒ ๋ฌด์‹œ
    public string Address { get; set; }
}

๋‚ ์งœ ํ˜•์‹ ์ œ์–ดํ•˜๊ธฐ ๐Ÿ“…

๋‚ ์งœ ํ˜•์‹์„ ์›ํ•˜๋Š” ๋Œ€๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์–ด:

public class Event
{
    public string Title { get; set; }
    
    [JsonProperty(PropertyName = "event_date")]
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public DateTime EventDate { get; set; }
    
    [JsonProperty(PropertyName = "created_at")]
    [JsonConverter(typeof(IsoDateTimeConverter), "yyyy-MM-dd")]
    public DateTime CreatedAt { get; set; }
}
C# ๊ฐ์ฒด์—์„œ JSON์œผ๋กœ ์ง๋ ฌํ™” ๊ณผ์ • C# ๊ฐ์ฒด public class Person { Name = "๊น€๊ฐœ๋ฐœ" Age = 28 Hobbies = [...] } JSON.NET ์ง๋ ฌํ™” ์ฒ˜๋ฆฌ JsonConvert.SerializeObject() JSON ๋ฌธ์ž์—ด { "Name": "๊น€๊ฐœ๋ฐœ", "Age": 28, "Hobbies": [ "์ฝ”๋”ฉ", "๋…์„œ", "๊ฒŒ์ž„" ] } ์„ค์ • ์˜ต์…˜ Formatting NullValueHandling ContractResolver

์กฐ๊ฑด๋ถ€ ์ง๋ ฌํ™” ๐Ÿ”„

ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ผ ์†์„ฑ์„ ์ง๋ ฌํ™”ํ• ์ง€ ๊ฒฐ์ •ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ShouldSerialize{PropertyName} ํŒจํ„ด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด:

public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public decimal? DiscountPrice { get; set; }
    
    // DiscountPrice๊ฐ€ null์ด ์•„๋‹ˆ๊ณ  Price๋ณด๋‹ค ์ž‘์„ ๋•Œ๋งŒ ์ง๋ ฌํ™”
    public bool ShouldSerializeDiscountPrice()
    {
        return DiscountPrice.HasValue && DiscountPrice.Value < Price;
    }
}

๋ณต์žกํ•œ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ์ง๋ ฌํ™” ๐ŸŒณ

JSON.NET์€ ๋ณต์žกํ•œ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„๋„ ์‰ฝ๊ฒŒ ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์žˆ์–ด. ์ˆœํ™˜ ์ฐธ์กฐ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” ReferenceLoopHandling ์„ค์ •์„ ์‚ฌ์šฉํ•ด:

// ์ˆœํ™˜ ์ฐธ์กฐ๊ฐ€ ์žˆ๋Š” ํด๋ž˜์Šค
public class Department
{
    public string Name { get; set; }
    public List<Employee> Employees { get; set; }
}

public class Employee
{
    public string Name { get; set; }
    public Department Department { get; set; }  // ์ˆœํ™˜ ์ฐธ์กฐ ๊ฐ€๋Šฅ์„ฑ
}

// ์ˆœํ™˜ ์ฐธ์กฐ ์ฒ˜๋ฆฌ ์„ค์ •
var settings = new JsonSerializerSettings
{
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,  // ์ˆœํ™˜ ์ฐธ์กฐ ๋ฌด์‹œ
    // ๋˜๋Š”
    // ReferenceLoopHandling = ReferenceLoopHandling.Serialize,  // $id์™€ $ref ์‚ฌ์šฉํ•˜์—ฌ ์ฐธ์กฐ ์œ ์ง€
    Formatting = Formatting.Indented
};

string json = JsonConvert.SerializeObject(department, settings);

๐Ÿ’ก ์„ฑ๋Šฅ ํŒ: ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ง๋ ฌํ™”ํ•  ๋•Œ๋Š” JsonTextWriter๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ ์ด์•ผ:

using (var stringWriter = new StringWriter())
using (var jsonWriter = new JsonTextWriter(stringWriter))
{
    var serializer = new JsonSerializer
    {
        Formatting = Formatting.Indented
    };
    
    serializer.Serialize(jsonWriter, largeObject);
    string json = stringWriter.ToString();
}

์žฌ๋Šฅ๋„ท ๊ฐ™์€ ์„œ๋น„์Šค์—์„œ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„์ด๋‚˜ ์„œ๋น„์Šค ์ •๋ณด๋ฅผ API๋กœ ์ œ๊ณตํ•  ๋•Œ ์ด๋Ÿฐ ์ง๋ ฌํ™” ๊ธฐ๋Šฅ์ด ์ •๋ง ์œ ์šฉํ•˜์ง€! ํŠนํžˆ ๋ณต์žกํ•œ ๊ฐ์ฒด ๊ตฌ์กฐ๋ฅผ ๊ฐ€์ง„ ๋ฐ์ดํ„ฐ๋ฅผ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•  ๋•Œ JSON.NET์˜ ๊ฐ•๋ ฅํ•œ ์ง๋ ฌํ™” ๊ธฐ๋Šฅ์ด ํฐ ๋„์›€์ด ๋  ๊ฑฐ์•ผ. ๐Ÿ˜Š

4. JSON ์—ญ์ง๋ ฌํ™”(Deserialization) ์™„๋ฒฝ ์ดํ•ด ๐Ÿ“ฅ

์—ญ์ง๋ ฌํ™”๋Š” JSON ๋ฌธ์ž์—ด์„ C# ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์ด์•ผ. ์ด๊ฒƒ๋„ JSON.NET์œผ๋กœ ์ •๋ง ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด! ๐ŸŽฏ

๊ธฐ๋ณธ ์—ญ์ง๋ ฌํ™” ๋ฐฉ๋ฒ• ๐Ÿ”„

๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ์—ญ์ง๋ ฌํ™” ๋ฐฉ๋ฒ•์€ JsonConvert.DeserializeObject<T>() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฑฐ์•ผ:

// JSON ๋ฌธ์ž์—ด
string json = @"{
  ""Name"": ""๊น€๊ฐœ๋ฐœ"",
  ""Age"": 28,
  ""Hobbies"": [""์ฝ”๋”ฉ"", ""๋…์„œ"", ""๊ฒŒ์ž„""]
}";

// Person ๊ฐ์ฒด๋กœ ์—ญ์ง๋ ฌํ™”
Person person = JsonConvert.DeserializeObject<Person>(json);

// ๊ฒฐ๊ณผ ํ™•์ธ
Console.WriteLine($"์ด๋ฆ„: {person.Name}, ๋‚˜์ด: {person.Age}");
Console.WriteLine($"์ทจ๋ฏธ: {string.Join(", ", person.Hobbies)}");

// ์ถœ๋ ฅ:
// ์ด๋ฆ„: ๊น€๊ฐœ๋ฐœ, ๋‚˜์ด: 28
// ์ทจ๋ฏธ: ์ฝ”๋”ฉ, ๋…์„œ, ๊ฒŒ์ž„

๋™์  ํƒ€์ž…์œผ๋กœ ์—ญ์ง๋ ฌํ™” ๐Ÿ”„

ํด๋ž˜์Šค๋ฅผ ๋ฏธ๋ฆฌ ์ •์˜ํ•˜์ง€ ์•Š๊ณ  dynamic ํƒ€์ž…์œผ๋กœ ์—ญ์ง๋ ฌํ™”ํ•  ์ˆ˜๋„ ์žˆ์–ด:

// dynamic์œผ๋กœ ์—ญ์ง๋ ฌํ™”
dynamic dynamicPerson = JsonConvert.DeserializeObject(json);

// ๋™์  ์†์„ฑ ์ ‘๊ทผ
Console.WriteLine($"์ด๋ฆ„: {dynamicPerson.Name}, ๋‚˜์ด: {dynamicPerson.Age}");
Console.WriteLine($"์ฒซ ๋ฒˆ์งธ ์ทจ๋ฏธ: {dynamicPerson.Hobbies[0]}");

๋ณต์žกํ•œ JSON ๊ตฌ์กฐ ์—ญ์ง๋ ฌํ™” ๐Ÿ—๏ธ

์ค‘์ฒฉ๋œ ๊ฐ์ฒด์™€ ๋ฐฐ์—ด์ด ์žˆ๋Š” ๋ณต์žกํ•œ JSON๋„ ์‰ฝ๊ฒŒ ์—ญ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์žˆ์–ด:

// ๋ณต์žกํ•œ JSON ๋ฌธ์ž์—ด
string complexJson = @"{
  ""OrderId"": ""ORD-12345"",
  ""Customer"": {
    ""Id"": 1001,
    ""Name"": ""ํ™๊ธธ๋™"",
    ""Email"": ""hong@example.com""
  },
  ""Items"": [
    {
      ""ProductId"": ""P100"",
      ""Name"": ""๋…ธํŠธ๋ถ"",
      ""Price"": 1200000,
      ""Quantity"": 1
    },
    {
      ""ProductId"": ""P200"",
      ""Name"": ""๋งˆ์šฐ์Šค"",
      ""Price"": 35000,
      ""Quantity"": 2
    }
  ],
  ""TotalAmount"": 1270000,
  ""OrderDate"": ""2023-05-15T14:30:00""
}";

// ํด๋ž˜์Šค ์ •์˜
public class Order
{
    public string OrderId { get; set; }
    public Customer Customer { get; set; }
    public List<OrderItem> Items { get; set; }
    public decimal TotalAmount { get; set; }
    public DateTime OrderDate { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
}

public class OrderItem
{
    public string ProductId { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int Quantity { get; set; }
}

// ์—ญ์ง๋ ฌํ™”
Order order = JsonConvert.DeserializeObject<Order>(complexJson);

// ๊ฒฐ๊ณผ ํ™•์ธ
Console.WriteLine($"์ฃผ๋ฌธ ID: {order.OrderId}, ๊ณ ๊ฐ๋ช…: {order.Customer.Name}");
Console.WriteLine($"์ฃผ๋ฌธ ์ƒํ’ˆ ์ˆ˜: {order.Items.Count}, ์ด์•ก: {order.TotalAmount:N0}์›");
JSON์—์„œ C# ๊ฐ์ฒด๋กœ ์—ญ์ง๋ ฌํ™” ๊ณผ์ • JSON ๋ฌธ์ž์—ด { "Name": "๊น€๊ฐœ๋ฐœ", "Age": 28, "Hobbies": [ "์ฝ”๋”ฉ", "๋…์„œ", "๊ฒŒ์ž„" ] } JSON.NET ์—ญ์ง๋ ฌํ™” ์ฒ˜๋ฆฌ JsonConvert.DeserializeObject() C# ๊ฐ์ฒด Person person = new Person { Name = "๊น€๊ฐœ๋ฐœ", Age = 28, Hobbies = { "์ฝ”๋”ฉ", "๋…์„œ", "๊ฒŒ์ž„" } }; ์—ญ์ง๋ ฌํ™” ์˜ต์…˜ TypeNameHandling MissingMemberHandling DateParseHandling

์ปค์Šคํ…€ ๋ณ€ํ™˜๊ธฐ(Converter) ์‚ฌ์šฉํ•˜๊ธฐ ๐Ÿ”ง

ํŠน๋ณ„ํ•œ ํ˜•์‹ ๋ณ€ํ™˜์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ JsonConverter๋ฅผ ์ƒ์†๋ฐ›์•„ ์ปค์Šคํ…€ ๋ณ€ํ™˜๊ธฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด:

// ์ปค์Šคํ…€ ๋‚ ์งœ ๋ณ€ํ™˜๊ธฐ ์˜ˆ์ œ
public class CustomDateTimeConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime);
    }
    
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.String)
        {
            string dateString = reader.Value.ToString();
            // "yyyy๋…„ MM์›” dd์ผ" ํ˜•์‹ ํŒŒ์‹ฑ
            if (DateTime.TryParseExact(dateString, "yyyy๋…„ MM์›” dd์ผ", CultureInfo.InvariantCulture, 
                DateTimeStyles.None, out DateTime result))
            {
                return result;
            }
        }
        
        // ๊ธฐ๋ณธ ์ฒ˜๋ฆฌ
        return DateTime.Parse(reader.Value.ToString());
    }
    
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(((DateTime)value).ToString("yyyy๋…„ MM์›” dd์ผ"));
    }
}

// ์ปค์Šคํ…€ ๋ณ€ํ™˜๊ธฐ ์‚ฌ์šฉ
var settings = new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new CustomDateTimeConverter() }
};

// ์—ญ์ง๋ ฌํ™”์— ์ ์šฉ
Event myEvent = JsonConvert.DeserializeObject<Event>(json, settings);

๋ˆ„๋ฝ๋œ ์†์„ฑ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๐Ÿ”

JSON์— ํด๋ž˜์Šค์˜ ์ผ๋ถ€ ์†์„ฑ์ด ๋ˆ„๋ฝ๋œ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์–ด:

var settings = new JsonSerializerSettings
{
    MissingMemberHandling = MissingMemberHandling.Error  // ๋ˆ„๋ฝ๋œ ์†์„ฑ์ด ์žˆ์œผ๋ฉด ์˜ค๋ฅ˜ ๋ฐœ์ƒ
    // ๋˜๋Š”
    // MissingMemberHandling = MissingMemberHandling.Ignore  // ๋ˆ„๋ฝ๋œ ์†์„ฑ ๋ฌด์‹œ
};

try
{
    Person person = JsonConvert.DeserializeObject<Person>(incompleteJson, settings);
}
catch (JsonSerializationException ex)
{
    Console.WriteLine($"์—ญ์ง๋ ฌํ™” ์˜ค๋ฅ˜: {ex.Message}");
}

JSON ๊ฒฝ๋กœ ์ง€์ •ํ•˜๊ธฐ ๐Ÿ›ค๏ธ

ํฐ JSON ๋ฌธ์„œ์—์„œ ํŠน์ • ๋ถ€๋ถ„๋งŒ ์—ญ์ง๋ ฌํ™”ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด JObject์™€ SelectToken์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด:

string largeJson = @"{
  ""response"": {
    ""status"": ""success"",
    ""data"": {
      ""users"": [
        {
          ""id"": 1,
          ""name"": ""๊น€์ฒ ์ˆ˜"",
          ""email"": ""kim@example.com""
        },
        {
          ""id"": 2,
          ""name"": ""์ด์˜ํฌ"",
          ""email"": ""lee@example.com""
        }
      ]
    }
  }
}";

// JObject๋กœ ํŒŒ์‹ฑ
JObject jsonObj = JObject.Parse(largeJson);

// ํŠน์ • ๊ฒฝ๋กœ์˜ ๋ฐ์ดํ„ฐ๋งŒ ์ถ”์ถœ
JArray usersArray = (JArray)jsonObj.SelectToken("response.data.users");

// ๋ฐฐ์—ด์„ List<User>๋กœ ๋ณ€ํ™˜
List<User> users = usersArray.ToObject<List<User>>();

// ๋˜๋Š” ์ฒซ ๋ฒˆ์งธ ์‚ฌ์šฉ์ž๋งŒ ์ถ”์ถœ
User firstUser = jsonObj.SelectToken("response.data.users[0]").ToObject<User>();

๐Ÿ’ก ๋ณด์•ˆ ํŒ: ์™ธ๋ถ€ ์†Œ์Šค์—์„œ ๋ฐ›์€ JSON์„ ์—ญ์ง๋ ฌํ™”ํ•  ๋•Œ๋Š” TypeNameHandling ์„ค์ •์— ์ฃผ์˜ํ•ด์•ผ ํ•ด. ์•…์˜์ ์ธ ํƒ€์ž… ์ •๋ณด๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ์–ด์„œ ๋ณด์•ˆ ์œ„ํ—˜์ด ์žˆ์–ด:

// ์•ˆ์ „ํ•œ ์„ค์ •
var settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.None  // ๊ธฐ๋ณธ๊ฐ’, ํƒ€์ž… ์ •๋ณด ๋ฌด์‹œ
};

// ์œ„ํ—˜ํ•  ์ˆ˜ ์žˆ๋Š” ์„ค์ • (์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์†Œ์Šค์—์„œ๋งŒ ์‚ฌ์šฉ)
var unsafeSettings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All  // ๋ชจ๋“  ํƒ€์ž… ์ •๋ณด ์‚ฌ์šฉ
};

์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฐ›์€ JSON ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ์ด๋Ÿฐ ์—ญ์ง๋ ฌํ™” ๊ธฐ๋Šฅ์ด ํ•„์ˆ˜์ ์ด์ง€! ํŠนํžˆ ์‚ฌ์šฉ์ž ์ž…๋ ฅ์ด๋‚˜ ์™ธ๋ถ€ API ์‘๋‹ต์„ ์•ˆ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋  ๊ฑฐ์•ผ. ๐Ÿ›ก๏ธ

5. LINQ to JSON์œผ๋กœ ๋™์  ๋ฐ์ดํ„ฐ ๋‹ค๋ฃจ๊ธฐ ๐Ÿ”

LINQ to JSON์€ JSON.NET์˜ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋กœ, JSON ๋ฐ์ดํ„ฐ๋ฅผ LINQ ์ฟผ๋ฆฌ๋กœ ์‰ฝ๊ฒŒ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค˜. ํŠนํžˆ ๋™์ ์ธ JSON ๊ตฌ์กฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ์ •๋ง ์œ ์šฉํ•ด! ๐Ÿงฉ

JObject์™€ JArray ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• ๐Ÿ“Š

LINQ to JSON์˜ ํ•ต์‹ฌ ํด๋ž˜์Šค๋Š” JObject(JSON ๊ฐ์ฒด์šฉ)์™€ JArray(JSON ๋ฐฐ์—ด์šฉ)์•ผ:

// JSON ๋ฌธ์ž์—ด
string json = @"{
  ""name"": ""์žฌ๋Šฅ๋„ท"",
  ""url"": ""https://www.jaenung.net"",
  ""services"": [
    {
      ""id"": 1,
      ""name"": ""์›น ๊ฐœ๋ฐœ"",
      ""price"": 500000
    },
    {
      ""id"": 2,
      ""name"": ""์•ฑ ๊ฐœ๋ฐœ"",
      ""price"": 700000
    },
    {
      ""id"": 3,
      ""name"": ""๋””์ž์ธ"",
      ""price"": 300000
    }
  ],
  ""established"": ""2020-01-15"",
  ""isActive"": true
}";

// JObject๋กœ ํŒŒ์‹ฑ
JObject jsonObj = JObject.Parse(json);

// ์†์„ฑ ์ ‘๊ทผํ•˜๊ธฐ
string name = (string)jsonObj["name"];
string url = (string)jsonObj["url"];
bool isActive = (bool)jsonObj["isActive"];

Console.WriteLine($"{name} ({url}) - ํ™œ์„ฑ ์ƒํƒœ: {isActive}");

// JArray ์ ‘๊ทผํ•˜๊ธฐ
JArray services = (JArray)jsonObj["services"];
Console.WriteLine($"์„œ๋น„์Šค ๊ฐœ์ˆ˜: {services.Count}");

// ๋ฐฐ์—ด ์š”์†Œ ์ ‘๊ทผํ•˜๊ธฐ
JObject firstService = (JObject)services[0];
string serviceName = (string)firstService["name"];
int price = (int)firstService["price"];
Console.WriteLine($"์ฒซ ๋ฒˆ์งธ ์„œ๋น„์Šค: {serviceName}, ๊ฐ€๊ฒฉ: {price:N0}์›");

LINQ ์ฟผ๋ฆฌ๋กœ JSON ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง ๐Ÿ”Ž

LINQ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JSON ๋ฐ์ดํ„ฐ๋ฅผ ์‰ฝ๊ฒŒ ํ•„ํ„ฐ๋งํ•˜๊ณ  ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์–ด:

// ๊ฐ€๊ฒฉ์ด 500,000์› ์ด์ƒ์ธ ์„œ๋น„์Šค ์ฐพ๊ธฐ
var expensiveServices = from s in services
                       where (int)s["price"] >= 500000
                       select s;

Console.WriteLine("๊ณ ๊ฐ€ ์„œ๋น„์Šค ๋ชฉ๋ก:");
foreach (var service in expensiveServices)
{
    Console.WriteLine($"- {service["name"]}: {(int)service["price"]:N0}์›");
}

// ์„œ๋น„์Šค ์ด๋ฆ„๋งŒ ์ถ”์ถœํ•˜๊ธฐ
var serviceNames = services.Select(s => (string)s["name"]).ToList();
Console.WriteLine($"์„œ๋น„์Šค ์ด๋ฆ„: {string.Join(", ", serviceNames)}");

// ๊ฐ€์žฅ ๋น„์‹ผ ์„œ๋น„์Šค ์ฐพ๊ธฐ
JObject mostExpensiveService = services
    .OrderByDescending(s => (int)s["price"])
    .First() as JObject;
    
Console.WriteLine($"๊ฐ€์žฅ ๋น„์‹ผ ์„œ๋น„์Šค: {mostExpensiveService["name"]} ({(int)mostExpensiveService["price"]:N0}์›)");

JSON ๋ฐ์ดํ„ฐ ์ˆ˜์ •ํ•˜๊ธฐ โœ๏ธ

LINQ to JSON์œผ๋กœ JSON ๋ฐ์ดํ„ฐ๋ฅผ ๋™์ ์œผ๋กœ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์–ด:

// ์†์„ฑ ๊ฐ’ ๋ณ€๊ฒฝํ•˜๊ธฐ
jsonObj["name"] = "์ƒˆ๋กœ์šด ์žฌ๋Šฅ๋„ท";

// ์ƒˆ ์†์„ฑ ์ถ”๊ฐ€ํ•˜๊ธฐ
jsonObj["description"] = "๋‹ค์–‘ํ•œ ์žฌ๋Šฅ์„ ๊ฑฐ๋ž˜ํ•˜๋Š” ํ”Œ๋žซํผ";
jsonObj["memberCount"] = 1500;

// ๋ฐฐ์—ด์— ์ƒˆ ํ•ญ๋ชฉ ์ถ”๊ฐ€ํ•˜๊ธฐ
JObject newService = new JObject
{
    ["id"] = 4,
    ["name"] = "๋งˆ์ผ€ํŒ…",
    ["price"] = 450000
};
services.Add(newService);

// ํŠน์ • ํ•ญ๋ชฉ ์ œ๊ฑฐํ•˜๊ธฐ
var serviceToRemove = services.FirstOrDefault(s => (int)s["id"] == 2);
if (serviceToRemove != null)
{
    services.Remove(serviceToRemove);
}

// ์ˆ˜์ •๋œ JSON ์ถœ๋ ฅํ•˜๊ธฐ
string updatedJson = jsonObj.ToString(Formatting.Indented);
Console.WriteLine(updatedJson);
LINQ to JSON ์ž‘๋™ ๋ฐฉ์‹ JSON ๋ฌธ์ž์—ด {"name": "์žฌ๋Šฅ๋„ท", "services": [ {"name": "์›น ๊ฐœ๋ฐœ", "price": 500000}, {"name": "์•ฑ ๊ฐœ๋ฐœ", "price": 700000}, ... ]} JObject/JArray JSON ๊ฐ์ฒด ํŠธ๋ฆฌ JObject โ”œโ”€ name: "์žฌ๋Šฅ๋„ท" โ””โ”€ services: JArray โ”œโ”€ JObject โ”œโ”€ JObject โ””โ”€ ... LINQ ์ฟผ๋ฆฌ from s in services where (int)s["price"] >= 500000 select s ๊ฒฐ๊ณผ: - ์›น ๊ฐœ๋ฐœ: 500000์› - ์•ฑ ๊ฐœ๋ฐœ: 700000์› JSON ํŠธ๋ฆฌ ๊ตฌ์กฐ ๋ฐ์ดํ„ฐ ์ฟผ๋ฆฌ ๋ฐ ๋ณ€ํ™˜

JSON ๊ฒฝ๋กœ ํ‘œํ˜„์‹ ์‚ฌ์šฉํ•˜๊ธฐ ๐Ÿ›ฃ๏ธ

๋ณต์žกํ•œ JSON ๊ตฌ์กฐ์—์„œ ํŠน์ • ๋ฐ์ดํ„ฐ๋ฅผ ์‰ฝ๊ฒŒ ์ฐพ๊ธฐ ์œ„ํ•ด SelectToken ๋ฉ”์„œ๋“œ์™€ JSON ๊ฒฝ๋กœ ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด:

// ๋ณต์žกํ•œ JSON ์˜ˆ์ œ
string complexJson = @"{
  ""company"": {
    ""name"": ""์žฌ๋Šฅ๋„ท"",
    ""departments"": [
      {
        ""name"": ""๊ฐœ๋ฐœํŒ€"",
        ""employees"": [
          {
            ""id"": 101,
            ""name"": ""๊น€๊ฐœ๋ฐœ"",
            ""skills"": [""C#"", ""ASP.NET"", ""JSON.NET""]
          },
          {
            ""id"": 102,
            ""name"": ""๋ฐ•์ฝ”๋”ฉ"",
            ""skills"": [""Java"", ""Spring"", ""React""]
          }
        ]
      },
      {
        ""name"": ""๋””์ž์ธํŒ€"",
        ""employees"": [
          {
            ""id"": 201,
            ""name"": ""์ด๋””์ž์ธ"",
            ""skills"": [""Photoshop"", ""Illustrator"", ""Figma""]
          }
        ]
      }
    ]
  }
}";

JObject root = JObject.Parse(complexJson);

// JSON ๊ฒฝ๋กœ ํ‘œํ˜„์‹์œผ๋กœ ๋ฐ์ดํ„ฐ ์ ‘๊ทผํ•˜๊ธฐ
string companyName = (string)root.SelectToken("company.name");
Console.WriteLine($"ํšŒ์‚ฌ๋ช…: {companyName}");

// ๋ฐฐ์—ด ์ธ๋ฑ์Šค ์‚ฌ์šฉํ•˜๊ธฐ
string firstDeptName = (string)root.SelectToken("company.departments[0].name");
Console.WriteLine($"์ฒซ ๋ฒˆ์งธ ๋ถ€์„œ: {firstDeptName}");

// ๋ฐฐ์—ด ๋‚ด ๋ชจ๋“  ์š”์†Œ ์„ ํƒํ•˜๊ธฐ
IEnumerable<JToken> allEmployees = root.SelectTokens("company.departments[*].employees[*]");
Console.WriteLine($"์ „์ฒด ์ง์› ์ˆ˜: {allEmployees.Count()}");

// ํŠน์ • ์กฐ๊ฑด์˜ ์š”์†Œ ์ฐพ๊ธฐ (ํ•„ํ„ฐ ํ‘œํ˜„์‹)
JToken csharpDev = root.SelectToken("company.departments[0].employees[?(@.skills[0]=='C#')]");
if (csharpDev != null)
{
    Console.WriteLine($"C# ๊ฐœ๋ฐœ์ž: {csharpDev["name"]}");
}

// ๋ชจ๋“  ์ง์› ์ด๋ฆ„ ์ถ”์ถœํ•˜๊ธฐ
IEnumerable<string> employeeNames = root
    .SelectTokens("company.departments[*].employees[*].name")
    .Select(t => (string)t);
    
Console.WriteLine($"์ง์› ๋ชฉ๋ก: {string.Join(", ", employeeNames)}");

JSON ์ƒ์„ฑํ•˜๊ธฐ ๐Ÿ—๏ธ

LINQ to JSON์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฒ˜์Œ๋ถ€ํ„ฐ JSON์„ ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์–ด:

// JObject๋กœ JSON ๊ฐ์ฒด ์ƒ์„ฑํ•˜๊ธฐ
JObject newPerson = new JObject
{
    ["name"] = "ํ™๊ธธ๋™",
    ["age"] = 30,
    ["email"] = "hong@example.com",
    ["isActive"] = true,
    ["address"] = new JObject
    {
        ["city"] = "์„œ์šธ",
        ["zipCode"] = "12345"
    },
    ["skills"] = new JArray("C#", "ASP.NET", "JSON.NET")
};

// JArray๋กœ JSON ๋ฐฐ์—ด ์ƒ์„ฑํ•˜๊ธฐ
JArray people = new JArray
{
    new JObject
    {
        ["name"] = "๊น€์ฒ ์ˆ˜",
        ["age"] = 25
    },
    new JObject
    {
        ["name"] = "์ด์˜ํฌ",
        ["age"] = 28
    },
    newPerson  // ์œ„์—์„œ ๋งŒ๋“  ๊ฐ์ฒด ์ถ”๊ฐ€
};

// ๋ฃจํŠธ ๊ฐ์ฒด ์ƒ์„ฑํ•˜๊ธฐ
JObject root = new JObject
{
    ["timestamp"] = DateTime.Now,
    ["count"] = people.Count,
    ["people"] = people
};

// ์ƒ์„ฑ๋œ JSON ์ถœ๋ ฅํ•˜๊ธฐ
string generatedJson = root.ToString(Formatting.Indented);
Console.WriteLine(generatedJson);

๐Ÿ’ก ์„ฑ๋Šฅ ํŒ: ๋Œ€์šฉ๋Ÿ‰ JSON์„ ์ฒ˜๋ฆฌํ•  ๋•Œ๋Š” JToken.Parse() ๋Œ€์‹  JToken.Load(JsonReader)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์ ์ด์•ผ:

using (StreamReader file = File.OpenText("largefile.json"))
using (JsonTextReader reader = new JsonTextReader(file))
{
    JObject largeJson = JObject.Load(reader);
    
    // ์ด์ œ largeJson์œผ๋กœ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ์–ด
}

์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ ๋‹ค์–‘ํ•œ API ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜, ๋™์ ์ธ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ LINQ to JSON์€ ์ •๋ง ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์•ผ. ํŠนํžˆ ์‚ฌ์šฉ์ž ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๋‚˜ ํ•„ํ„ฐ๋ง๋œ ์„œ๋น„์Šค ๋ชฉ๋ก์„ ์ƒ์„ฑํ•  ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์ง€! ๐Ÿ”

6. JSON ์Šคํ‚ค๋งˆ ๊ฒ€์ฆํ•˜๊ธฐ โœ…

JSON ์Šคํ‚ค๋งˆ๋Š” JSON ๋ฐ์ดํ„ฐ์˜ ๊ตฌ์กฐ์™€ ํ˜•์‹์„ ์ •์˜ํ•˜๊ณ  ๊ฒ€์ฆํ•˜๋Š” ๊ฐ•๋ ฅํ•œ ๋ฐฉ๋ฒ•์ด์•ผ. JSON.NET์€ JSON ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์„œ ๋ฐ์ดํ„ฐ์˜ ์œ ํšจ์„ฑ์„ ์‰ฝ๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์ง€! ๐Ÿ›ก๏ธ

JSON ์Šคํ‚ค๋งˆ ๊ธฐ๋ณธ ๊ฐœ๋… ๐Ÿ“‹

JSON ์Šคํ‚ค๋งˆ๋Š” JSON ๋ฌธ์„œ๊ฐ€ ๋”ฐ๋ผ์•ผ ํ•  ๊ทœ์น™์„ ์ •์˜ํ•ด. ์†์„ฑ์˜ ํƒ€์ž…, ํ•„์ˆ˜ ์—ฌ๋ถ€, ๊ฐ’ ๋ฒ”์œ„ ๋“ฑ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์–ด:

// ๊ฐ„๋‹จํ•œ JSON ์Šคํ‚ค๋งˆ ์˜ˆ์ œ
string schema = @"{
  ""type"": ""object"",
  ""required"": [""name"", ""email"", ""age""],
  ""properties"": {
    ""name"": {
      ""type"": ""string"",
      ""minLength"": 2,
      ""maxLength"": 50
    },
    ""email"": {
      ""type"": ""string"",
      ""format"": ""email""
    },
    ""age"": {
      ""type"": ""integer"",
      ""minimum"": 18,
      ""maximum"": 120
    },
    ""website"": {
      ""type"": ""string"",
      ""format"": ""uri""
    },
    ""tags"": {
      ""type"": ""array"",
      ""items"": {
        ""type"": ""string""
      }
    }
  }
}";

JSON ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ ๊ตฌํ˜„ํ•˜๊ธฐ ๐Ÿ”

JSON.NET์—์„œ ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Newtonsoft.Json.Schema ํŒจํ‚ค์ง€๋ฅผ ์ถ”๊ฐ€๋กœ ์„ค์น˜ํ•ด์•ผ ํ•ด:

// NuGet ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ € ์ฝ˜์†”์—์„œ:
PM> Install-Package Newtonsoft.Json.Schema

์ด์ œ ์Šคํ‚ค๋งˆ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JSON ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ์–ด:

using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Linq;

// ์Šคํ‚ค๋งˆ ํŒŒ์‹ฑ
JSchema jsonSchema = JSchema.Parse(schema);

// ๊ฒ€์ฆํ•  JSON ๋ฐ์ดํ„ฐ
string json = @"{
  ""name"": ""ํ™๊ธธ๋™"",
  ""email"": ""hong@example.com"",
  ""age"": 25,
  ""website"": ""https://example.com"",
  ""tags"": [""๊ฐœ๋ฐœ์ž"", ""C#"", ""JSON""]
}";

// JSON ํŒŒ์‹ฑ
JObject jsonObject = JObject.Parse(json);

// ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ
bool isValid = jsonObject.IsValid(jsonSchema, out IList<string> errorMessages);

if (isValid)
{
    Console.WriteLine("JSON ๋ฐ์ดํ„ฐ๊ฐ€ ์Šคํ‚ค๋งˆ์— ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.");
}
else
{
    Console.WriteLine("JSON ๋ฐ์ดํ„ฐ๊ฐ€ ์Šคํ‚ค๋งˆ์— ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค:");
    foreach (string error in errorMessages)
    {
        Console.WriteLine($"- {error}");
    }
}

๋ณต์žกํ•œ ์Šคํ‚ค๋งˆ ์˜ˆ์ œ ๐Ÿงฉ

๋” ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ์Šคํ‚ค๋งˆ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด์ž:

// ์žฌ๋Šฅ๋„ท ์„œ๋น„์Šค ๋ชฉ๋ก์„ ์œ„ํ•œ ์Šคํ‚ค๋งˆ
string serviceListSchema = @"{
  ""type"": ""object"",
  ""required"": [""services""],
  ""properties"": {
    ""services"": {
      ""type"": ""array"",
      ""items"": {
        ""type"": ""object"",
        ""required"": [""id"", ""name"", ""price"", ""category""],
        ""properties"": {
          ""id"": {
            ""type"": ""integer"",
            ""minimum"": 1
          },
          ""name"": {
            ""type"": ""string"",
            ""minLength"": 3,
            ""maxLength"": 100
          },
          ""description"": {
            ""type"": [""string"", ""null""],
            ""maxLength"": 1000
          },
          ""price"": {
            ""type"": ""number"",
            ""minimum"": 0
          },
          ""category"": {
            ""type"": ""string"",
            ""enum"": [""๊ฐœ๋ฐœ"", ""๋””์ž์ธ"", ""๋งˆ์ผ€ํŒ…"", ""๋ฒˆ์—ญ"", ""๊ธฐํƒ€""]
          },
          ""tags"": {
            ""type"": ""array"",
            ""items"": {
              ""type"": ""string""
            },
            ""maxItems"": 10
          },
          ""rating"": {
            ""type"": ""number"",
            ""minimum"": 0,
            ""maximum"": 5,
            ""multipleOf"": 0.1
          },
          ""created_at"": {
            ""type"": ""string"",
            ""format"": ""date-time""
          }
        }
      }
    },
    ""total_count"": {
      ""type"": ""integer"",
      ""minimum"": 0
    },
    ""page"": {
      ""type"": ""integer"",
      ""minimum"": 1
    },
    ""page_size"": {
      ""type"": ""integer"",
      ""minimum"": 1,
      ""maximum"": 100
    }
  }
}";
JSON ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ ํ”„๋กœ์„ธ์Šค JSON ์Šคํ‚ค๋งˆ {"type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" } } JSON ๋ฐ์ดํ„ฐ { "name": "ํ™๊ธธ๋™", "age": 25, "email": "hong@example.com" } JSON.NET ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ jsonObject.IsValid(jsonSchema) ๊ฒ€์ฆ ๊ฒฐ๊ณผ ์œ ํšจํ•จ / ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ๋ชฉ๋ก

์Šคํ‚ค๋งˆ ๊ฒ€์ฆ์„ ์œ„ํ•œ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ๐Ÿ”ง

JSON.NET Schema๋Š” ๋‹ค์–‘ํ•œ ๊ณ ๊ธ‰ ๊ฒ€์ฆ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด:

// ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ
JSchemaValidatingReader reader = new JSchemaValidatingReader(new JsonTextReader(new StringReader(json)));
reader.Schema = jsonSchema;

// ๊ฒ€์ฆ ์˜ค๋ฅ˜ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ
reader.ValidationEventHandler += (sender, args) => {
    Console.WriteLine($"๊ฒ€์ฆ ์˜ค๋ฅ˜: {args.Message}");
};

// ๊ฒ€์ฆํ•˜๋ฉด์„œ JSON ์ฝ๊ธฐ
JsonSerializer serializer = new JsonSerializer();
try
{
    var obj = serializer.Deserialize<ServiceList>(reader);
    Console.WriteLine("๊ฒ€์ฆ ๋ฐ ์—ญ์ง๋ ฌํ™” ์„ฑ๊ณต!");
}
catch (JSchemaValidationException ex)
{
    Console.WriteLine($"๊ฒ€์ฆ ์‹คํŒจ: {ex.Message}");
}

์Šคํ‚ค๋งˆ ์ƒ์„ฑํ•˜๊ธฐ ๐Ÿ› ๏ธ

๊ธฐ์กด C# ํด๋ž˜์Šค์—์„œ JSON ์Šคํ‚ค๋งˆ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ์–ด:

// ํด๋ž˜์Šค ์ •์˜
public class Product
{
    public int Id { get; set; }
    
    [Required]
    [StringLength(100, MinimumLength = 3)]
    public string Name { get; set; }
    
    [Range(0, double.MaxValue)]
    public decimal Price { get; set; }
    
    public string[] Categories { get; set; }
    
    [DataType(DataType.Date)]
    public DateTime CreatedAt { get; set; }
}

// ์Šคํ‚ค๋งˆ ์ƒ์„ฑ
JSchemaGenerator generator = new JSchemaGenerator();
JSchema productSchema = generator.Generate(typeof(Product));

// ์ƒ์„ฑ๋œ ์Šคํ‚ค๋งˆ ์ถœ๋ ฅ
string schemaJson = productSchema.ToString();
Console.WriteLine(schemaJson);

๐Ÿ’ก ์ค‘์š”: Newtonsoft.Json.Schema ํŒจํ‚ค์ง€๋Š” ์ƒ์—…์šฉ์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๋ผ์ด์„ผ์Šค๊ฐ€ ํ•„์š”ํ•ด. ๋ฌด๋ฃŒ๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด NJsonSchema์™€ ๊ฐ™์€ ๋Œ€์•ˆ์„ ๊ณ ๋ คํ•ด๋ณผ ์ˆ˜ ์žˆ์–ด:

// NJsonSchema ์‚ฌ์šฉ ์˜ˆ
using NJsonSchema;

// ์Šคํ‚ค๋งˆ ์ƒ์„ฑ
var schema = JsonSchema.FromType<Product>();
var schemaJson = schema.ToJson();

// ๊ฒ€์ฆ
var validationErrors = schema.Validate(json);
foreach (var error in validationErrors)
{
    Console.WriteLine(error.ToString());
}

์žฌ๋Šฅ๋„ท๊ณผ ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์ œ์ถœํ•œ ์„œ๋น„์Šค ์ •๋ณด๋‚˜ ํ”„๋กœํ•„ ๋ฐ์ดํ„ฐ์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•  ๋•Œ JSON ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ์ด ๋งค์šฐ ์œ ์šฉํ•ด. ํŠนํžˆ API๋ฅผ ํ†ตํ•ด ๋ฐ›์€ ๋ฐ์ดํ„ฐ๊ฐ€ ์˜ˆ์ƒํ•œ ํ˜•์‹์„ ๋”ฐ๋ฅด๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜์ง€! ๐Ÿ“Š

7. ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ๋ฐ ์„ฑ๋Šฅ ์ตœ์ ํ™” โšก

JSON.NET์€ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ ์™ธ์—๋„ ๋‹ค์–‘ํ•œ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ๊ณผ ์„ฑ๋Šฅ ์ตœ์ ํ™” ์˜ต์…˜์„ ์ œ๊ณตํ•ด. ์ด์ œ ๋” ๋ณต์žกํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž! ๐Ÿš€

๋‹คํ˜•์„ฑ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๐Ÿงฌ

์ƒ์† ๊ด€๊ณ„๊ฐ€ ์žˆ๋Š” ํด๋ž˜์Šค๋ฅผ ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™”ํ•  ๋•Œ๋Š” TypeNameHandling ์„ค์ •์„ ์‚ฌ์šฉํ•ด:

// ๊ธฐ๋ณธ ํด๋ž˜์Šค์™€ ํŒŒ์ƒ ํด๋ž˜์Šค
public abstract class Animal
{
    public string Name { get; set; }
}

public class Dog : Animal
{
    public string Breed { get; set; }
    public bool IsGoodBoy { get; set; } = true;
}

public class Cat : Animal
{
    public int LivesLeft { get; set; } = 9;
    public bool LikesMilk { get; set; }
}

// ๋‹คํ˜•์„ฑ ์ปฌ๋ ‰์…˜ ์ƒ์„ฑ
List<Animal> animals = new List<Animal>
{
    new Dog { Name = "๋ฐ”๋‘‘์ด", Breed = "์ง„๋—๊ฐœ" },
    new Cat { Name = "๋‚˜๋น„", LikesMilk = true }
};

// ํƒ€์ž… ์ •๋ณด ํฌํ•จํ•˜์—ฌ ์ง๋ ฌํ™”
var settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto,
    Formatting = Formatting.Indented
};

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

// ์—ญ์ง๋ ฌํ™” (ํƒ€์ž… ์ •๋ณด ์‚ฌ์šฉ)
List<Animal> deserializedAnimals = JsonConvert.DeserializeObject<List<Animal>>(json, settings);

// ์›๋ž˜ ํƒ€์ž…์œผ๋กœ ์บ์ŠคํŒ… ๊ฐ€๋Šฅ
Dog dog = deserializedAnimals[0] as Dog;
Cat cat = deserializedAnimals[1] as Cat;

Console.WriteLine($"{dog.Name}์€(๋Š”) {(dog.IsGoodBoy ? "์ฐฉํ•œ" : "์žฅ๋‚œ๊พธ๋Ÿฌ๊ธฐ")} {dog.Breed}์ž…๋‹ˆ๋‹ค.");
Console.WriteLine($"{cat.Name}์€(๋Š”) ์šฐ์œ ๋ฅผ {(cat.LikesMilk ? "์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค" : "์‹ซ์–ดํ•ฉ๋‹ˆ๋‹ค")}.");

์ปค์Šคํ…€ ์ปจํŠธ๋ž™ํŠธ ๋ฆฌ์กธ๋ฒ„ ๋งŒ๋“ค๊ธฐ ๐Ÿ”ง

์†์„ฑ ์ด๋ฆ„ ๋ณ€ํ™˜ ๊ทœ์น™์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•˜๋ ค๋ฉด IContractResolver๋ฅผ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ ๊ธฐ์กด ๋ฆฌ์กธ๋ฒ„๋ฅผ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์–ด:

// ์ปค์Šคํ…€ ์ปจํŠธ๋ž™ํŠธ ๋ฆฌ์กธ๋ฒ„
public class CustomContractResolver : DefaultContractResolver
{
    protected override string ResolvePropertyName(string propertyName)
    {
        // ์˜ˆ: ๋ชจ๋“  ์†์„ฑ ์ด๋ฆ„์„ ์†Œ๋ฌธ์ž๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์–ธ๋”์Šค์ฝ”์–ด๋กœ ๊ตฌ๋ถ„
        return string.Concat(propertyName.Select((x, i) => i > 0 && char.IsUpper(x) ? 
            "_" + char.ToLower(x) : char.ToLower(x).ToString()));
    }
    
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        
        // ํŠน์ • ํƒ€์ž…์˜ ์†์„ฑ์— ๋Œ€ํ•œ ์ปค์Šคํ…€ ์ฒ˜๋ฆฌ
        if (property.PropertyType == typeof(DateTime))
        {
            property.Converter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd" };
        }
        
        return property;
    }
}

// ์ปค์Šคํ…€ ๋ฆฌ์กธ๋ฒ„ ์‚ฌ์šฉ
var settings = new JsonSerializerSettings
{
    ContractResolver = new CustomContractResolver(),
    Formatting = Formatting.Indented
};

string json = JsonConvert.SerializeObject(myObject, settings);

์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ธฐ๋ฒ• โšก

๋Œ€์šฉ๋Ÿ‰ JSON ์ฒ˜๋ฆฌ ์‹œ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž:

// 1. JsonSerializer ์žฌ์‚ฌ์šฉํ•˜๊ธฐ
// ๋งค๋ฒˆ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํšจ์œจ์ 
private static readonly JsonSerializer Serializer = new JsonSerializer
{
    NullValueHandling = NullValueHandling.Ignore,
    DefaultValueHandling = DefaultValueHandling.Ignore
};

// 2. ์ŠคํŠธ๋ฆฌ๋ฐ ์ฒ˜๋ฆฌ ์‚ฌ์šฉํ•˜๊ธฐ
public void SerializeToFile<T>(T obj, string filePath)
{
    using (var file = File.CreateText(filePath))
    using (var writer = new JsonTextWriter(file))
    {
        writer.Formatting = Formatting.Indented;
        Serializer.Serialize(writer, obj);
    }
}

public T DeserializeFromFile<T>(string filePath)
{
    using (var file = File.OpenText(filePath))
    using (var reader = new JsonTextReader(file))
    {
        return Serializer.Deserialize<T>(reader);
    }
}

// 3. ๋Œ€์šฉ๋Ÿ‰ ๋ฐฐ์—ด ์ŠคํŠธ๋ฆฌ๋ฐ ์ฒ˜๋ฆฌ
public IEnumerable<T> StreamArrayFromFile<T>(string filePath)
{
    using (var file = File.OpenText(filePath))
    using (var reader = new JsonTextReader(file))
    {
        // ๋ฐฐ์—ด ์‹œ์ž‘ ํ† ํฐ ํ™•์ธ
        if (reader.Read() && reader.TokenType == JsonToken.StartArray)
        {
            // ๋ฐฐ์—ด ์š”์†Œ๋ฅผ ํ•˜๋‚˜์”ฉ ์ฝ์–ด์„œ ๋ฐ˜ํ™˜
            while (reader.Read() && reader.TokenType != JsonToken.EndArray)
            {
                yield return Serializer.Deserialize<T>(reader);
            }
        }
    }
}
JSON.NET ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ธฐ๋ฒ• ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ๋น„๊ต ์ผ๋ฐ˜ ๋ฐฉ์‹ JsonConvert.SerializeObject() ์ŠคํŠธ๋ฆฌ๋ฐ ๋ฐฉ์‹ JsonTextWriter + JsonSerializer ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ธฐ๋ฒ• JsonSerializer ์žฌ์‚ฌ์šฉ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ๋น„์šฉ ์ ˆ๊ฐ static readonly ํ™œ์šฉ ์ŠคํŠธ๋ฆฌ๋ฐ ์ฒ˜๋ฆฌ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์— ํšจ์œจ์  ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ๊ฐ์†Œ ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ์ œ์™ธ NullValueHandling.Ignore DefaultValueHandling.Ignore

์ปค์Šคํ…€ JsonConverter ๊ตฌํ˜„ํ•˜๊ธฐ ๐Ÿ› ๏ธ

ํŠน๋ณ„ํ•œ ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™” ๋กœ์ง์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ JsonConverter๋ฅผ ์ƒ์†๋ฐ›์•„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด:

// ์ปค์Šคํ…€ ์—ด๊ฑฐํ˜• ๋ณ€ํ™˜๊ธฐ ์˜ˆ์ œ
public class StringEnumConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType.IsEnum;
    }
    
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.String)
        {
            string enumText = reader.Value.ToString();
            return Enum.Parse(objectType, enumText, true);
        }
        
        return Enum.ToObject(objectType, reader.Value);
    }
    
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(value.ToString());
    }
}

// ์‚ฌ์šฉ ์˜ˆ
public enum UserRole { Admin, Editor, Viewer }

public class User
{
    public string Name { get; set; }
    
    [JsonConverter(typeof(StringEnumConverter))]
    public UserRole Role { get; set; }
}

์กฐ๊ฑด๋ถ€ ์†์„ฑ ์ง๋ ฌํ™” ๐Ÿ”„

ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ผ ์†์„ฑ์„ ์ง๋ ฌํ™”ํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•:

// 1. ShouldSerialize{PropertyName} ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ
public class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public decimal? SalePrice { get; set; }
    
    // SalePrice๊ฐ€ null์ด ์•„๋‹ˆ๊ณ  Price๋ณด๋‹ค ์ž‘์„ ๋•Œ๋งŒ ์ง๋ ฌํ™”
    public bool ShouldSerializeSalePrice()
    {
        return SalePrice.HasValue && SalePrice.Value < Price;
    }
}

// 2. JsonProperty ํŠน์„ฑ์˜ Required ์†์„ฑ ์‚ฌ์šฉ
public class Customer
{
    [JsonProperty(Required = Required.Always)]
    public string Name { get; set; }
    
    [JsonProperty(Required = Required.Default)]
    public string Email { get; set; }
    
    [JsonProperty(Required = Required.DisallowNull)]
    public string Phone { get; set; }
}

๋™์  JSON ์ƒ์„ฑ ์ตœ์ ํ™” ๐Ÿ”„

๋งŽ์€ ์–‘์˜ ๋™์  JSON์„ ์ƒ์„ฑํ•  ๋•Œ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•:

// ๋Œ€๋Ÿ‰์˜ JSON ๊ฐ์ฒด ์ƒ์„ฑ ์ตœ์ ํ™”
public string GenerateLargeJson(IEnumerable<Product> products)
{
    StringBuilder sb = new StringBuilder();
    StringWriter sw = new StringWriter(sb);
    
    using (JsonWriter writer = new JsonTextWriter(sw))
    {
        writer.Formatting = Formatting.Indented;
        
        writer.WriteStartObject();
        
        writer.WritePropertyName("timestamp");
        writer.WriteValue(DateTime.Now);
        
        writer.WritePropertyName("products");
        writer.WriteStartArray();
        
        foreach (var product in products)
        {
            writer.WriteStartObject();
            
            writer.WritePropertyName("id");
            writer.WriteValue(product.Id);
            
            writer.WritePropertyName("name");
            writer.WriteValue(product.Name);
            
            writer.WritePropertyName("price");
            writer.WriteValue(product.Price);
            
            writer.WriteEndObject();
        }
        
        writer.WriteEndArray();
        writer.WriteEndObject();
    }
    
    return sb.ToString();
}

๐Ÿ’ก ์„ฑ๋Šฅ ์ธก์ • ํŒ: JSON.NET์˜ ์„ฑ๋Šฅ์„ ์ธก์ •ํ•˜๊ณ  ์ตœ์ ํ™”ํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•ด ๋ณด์„ธ์š”:

  1. BenchmarkDotNet - ๋‹ค์–‘ํ•œ ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™” ๋ฐฉ๋ฒ•์˜ ์„ฑ๋Šฅ ๋น„๊ต
  2. dotMemory - ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ๋ถ„์„
  3. Visual Studio Profiler - CPU ์‚ฌ์šฉ๋Ÿ‰ ๋ฐ ๋ณ‘๋ชฉ ์ง€์  ์‹๋ณ„

์žฌ๋Šฅ๋„ท๊ณผ ๊ฐ™์€ ๋Œ€๊ทœ๋ชจ ํ”Œ๋žซํผ์—์„œ๋Š” API ์‘๋‹ต ์‹œ๊ฐ„๊ณผ ์„œ๋ฒ„ ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ์„ ์ตœ์ ํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด. ์œ„์—์„œ ๋ฐฐ์šด JSON.NET ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ธฐ๋ฒ•์„ ์ ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ! ๐Ÿš€

8. ์‹ค์ „ ์˜ˆ์ œ: ์›น API์™€ JSON.NET ๐ŸŒ

์ด์ œ JSON.NET์„ ์‹ค์ œ ์›น API ๊ฐœ๋ฐœ์— ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž! ASP.NET Core๋ฅผ ์‚ฌ์šฉํ•œ ์›น API์—์„œ JSON.NET์„ ํ™œ์šฉํ•˜๋Š” ๋‹ค์–‘ํ•œ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณผ ๊ฑฐ์•ผ. ๐Ÿš€

ASP.NET Core์—์„œ JSON.NET ์„ค์ •ํ•˜๊ธฐ โš™๏ธ

ASP.NET Core 3.0๋ถ€ํ„ฐ๋Š” ๊ธฐ๋ณธ JSON ์ง๋ ฌํ™” ๋„๊ตฌ๋กœ System.Text.Json์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ, JSON.NET์„ ๊ณ„์† ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•  ์ˆ˜ ์žˆ์–ด:

// NuGet ํŒจํ‚ค์ง€ ์„ค์น˜
// PM> Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson

// Startup.cs์˜ ConfigureServices ๋ฉ”์„œ๋“œ์—์„œ
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
        .AddNewtonsoftJson(options =>
        {
            // ์ˆœํ™˜ ์ฐธ์กฐ ์ฒ˜๋ฆฌ
            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            
            // ์†์„ฑ๋ช… ์นด๋ฉœ ์ผ€์ด์Šค๋กœ ๋ณ€ํ™˜
            options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            
            // null ๊ฐ’ ๋ฌด์‹œ
            options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
            
            // ๋“ค์—ฌ์“ฐ๊ธฐ ์ ์šฉ (๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋งŒ ๊ถŒ์žฅ)
            options.SerializerSettings.Formatting = Formatting.Indented;
        });
}

API ์ปจํŠธ๋กค๋Ÿฌ์—์„œ JSON ์‘๋‹ต ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ๐ŸŽจ

์ปจํŠธ๋กค๋Ÿฌ์—์„œ JSON ์‘๋‹ต์„ ์„ธ๋ฐ€ํ•˜๊ฒŒ ์ œ์–ดํ•˜๋Š” ๋ฐฉ๋ฒ•:

[ApiController]
[Route("api/[controller]")]
public class ServicesController : ControllerBase
{
    private readonly IServiceRepository _repository;
    
    public ServicesController(IServiceRepository repository)
    {
        _repository = repository;
    }
    
    // ํŠน์ • ์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ JSON ์„ค์ • ์ปค์Šคํ„ฐ๋งˆ์ด์ง•
    [HttpGet]
    [JsonProperty(PropertyName = "service_list")]
    public async Task<IActionResult> GetServices()
    {
        var services = await _repository.GetAllServicesAsync();
        
        // ์‘๋‹ต ๊ฐ์ฒด ๊ตฌ์„ฑ
        var response = new
        {
            timestamp = DateTime.Now,
            total_count = services.Count,
            services = services
        };
        
        // ํŠน์ • ์ง๋ ฌํ™” ์„ค์ • ์ ์šฉ
        var serializerSettings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver(),
            Formatting = Formatting.Indented
        };
        
        // JSON ์‘๋‹ต ๋ฐ˜ํ™˜
        return new JsonResult(response, serializerSettings);
    }
    
    // JsonConverter ํŠน์„ฑ ์‚ฌ์šฉ ์˜ˆ์ œ
    [HttpGet("{id}")]
    public async Task<ActionResult<ServiceDto>> GetService(int id)
    {
        var service = await _repository.GetServiceByIdAsync(id);
        
        if (service == null)
        {
            return NotFound();
        }
        
        return service;
    }
}

API ์š”์ฒญ ๋ณธ๋ฌธ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๐Ÿ“

ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ณด๋‚ธ JSON ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•:

[HttpPost]
public async Task<ActionResult<ServiceDto>> CreateService([FromBody] ServiceCreateDto serviceDto)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    
    // DTO๋ฅผ ๋„๋ฉ”์ธ ๋ชจ๋ธ๋กœ ๋ณ€ํ™˜
    var service = new Service
    {
        Name = serviceDto.Name,
        Description = serviceDto.Description,
        Price = serviceDto.Price,
        CategoryId = serviceDto.CategoryId
    };
    
    // ์ €์žฅ์†Œ์— ์ €์žฅ
    await _repository.AddServiceAsync(service);
    
    // ์ƒ์„ฑ๋œ ์„œ๋น„์Šค ๋ฐ˜ํ™˜
    var createdService = new ServiceDto
    {
        Id = service.Id,
        Name = service.Name,
        Description = service.Description,
        Price = service.Price,
        Category = service.Category?.Name
    };
    
    return CreatedAtAction(nameof(GetService), new { id = service.Id }, createdService);
}
์›น API์—์„œ JSON.NET ํ™œ์šฉ ํ๋ฆ„ ํด๋ผ์ด์–ธํŠธ ์›น/๋ชจ๋ฐ”์ผ ์•ฑ ASP.NET Core ์„œ๋ฒ„ API ์ปจํŠธ๋กค๋Ÿฌ ์š”์ฒญ/์‘๋‹ต ์ฒ˜๋ฆฌ JSON.NET ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™” ๋ฐ์ดํ„ฐ ์•ก์„ธ์Šค ์ €์žฅ์†Œ/๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค HTTP POST JSON ์š”์ฒญ JSON ์‘๋‹ต ์žฌ๋Šฅ๋„ท API: ์„œ๋น„์Šค ๋“ฑ๋ก, ๊ฒ€์ƒ‰, ๊ฒฐ์ œ ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ JSON์œผ๋กœ ์ฃผ๊ณ ๋ฐ›์Œ JSON.NET์ด ๋ณต์žกํ•œ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„์™€ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌ

API ์‘๋‹ต ํ˜•์‹ ํ‘œ์ค€ํ™”ํ•˜๊ธฐ ๐Ÿ“Š

์ผ๊ด€๋œ API ์‘๋‹ต ํ˜•์‹์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•œ ๋ž˜ํผ ํด๋ž˜์Šค ์˜ˆ์ œ:

// API ์‘๋‹ต ๋ž˜ํผ ํด๋ž˜์Šค
public class ApiResponse<T>
{
    [JsonProperty("success")]
    public bool Success { get; set; }
    
    [JsonProperty("message")]
    public string Message { get; set; }
    
    [JsonProperty("data")]
    public T Data { get; set; }
    
    [JsonProperty("timestamp")]
    public DateTime Timestamp { get; set; } = DateTime.Now;
    
    // ์„ฑ๊ณต ์‘๋‹ต ์ƒ์„ฑ
    public static ApiResponse<T> CreateSuccess(T data, string message = "์š”์ฒญ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
    {
        return new ApiResponse<T>
        {
            Success = true,
            Message = message,
            Data = data
        };
    }
    
    // ์˜ค๋ฅ˜ ์‘๋‹ต ์ƒ์„ฑ
    public static ApiResponse<T> CreateError(string message)
    {
        return new ApiResponse<T>
        {
            Success = false,
            Message = message,
            Data = default
        };
    }
}

// ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์‚ฌ์šฉ ์˜ˆ
[HttpGet]
public async Task<ActionResult<ApiResponse<List<ServiceDto>>>> GetServices()
{
    try
    {
        var services = await _repository.GetAllServicesAsync();
        return ApiResponse<List<ServiceDto>>.CreateSuccess(services);
    }
    catch (Exception ex)
    {
        // ๋กœ๊น… ์ถ”๊ฐ€
        return ApiResponse<List<ServiceDto>>.CreateError("์„œ๋น„์Šค ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ค๋Š” ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.");
    }
}

JSON ํŒจ์น˜(PATCH) ๊ตฌํ˜„ํ•˜๊ธฐ ๐Ÿ”„

๋ถ€๋ถ„ ์—…๋ฐ์ดํŠธ๋ฅผ ์œ„ํ•œ JSON ํŒจ์น˜ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•:

// NuGet ํŒจํ‚ค์ง€ ์„ค์น˜
// PM> Install-Package Microsoft.AspNetCore.JsonPatch

[HttpPatch("{id}")]
public async Task<IActionResult> UpdateServicePartial(int id, [FromBody] JsonPatchDocument<ServiceUpdateDto> patchDoc)
{
    if (patchDoc == null)
    {
        return BadRequest();
    }
    
    var service = await _repository.GetServiceByIdAsync(id);
    
    if (service == null)
    {
        return NotFound();
    }
    
    // ์—”ํ‹ฐํ‹ฐ๋ฅผ DTO๋กœ ๋ณ€ํ™˜
    var serviceToUpdate = new ServiceUpdateDto
    {
        Name = service.Name,
        Description = service.Description,
        Price = service.Price,
        IsActive = service.IsActive
    };
    
    // ํŒจ์น˜ ๋ฌธ์„œ ์ ์šฉ
    patchDoc.ApplyTo(serviceToUpdate, ModelState);
    
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
    
    // DTO๋ฅผ ์—”ํ‹ฐํ‹ฐ์— ๋ฐ˜์˜
    service.Name = serviceToUpdate.Name;
    service.Description = serviceToUpdate.Description;
    service.Price = serviceToUpdate.Price;
    service.IsActive = serviceToUpdate.IsActive;
    
    await _repository.UpdateServiceAsync(service);
    
    return NoContent();
}

JSON ์‘๋‹ต ์บ์‹ฑ ๊ตฌํ˜„ํ•˜๊ธฐ โšก

์ž์ฃผ ์š”์ฒญ๋˜๋Š” JSON ์‘๋‹ต์„ ์บ์‹ฑํ•˜์—ฌ ์„ฑ๋Šฅ ํ–ฅ์ƒ์‹œํ‚ค๊ธฐ:

// ์บ์‹ฑ ๋ฏธ๋“ค์›จ์–ด ์„ค์ • (Startup.cs)
public void ConfigureServices(IServiceCollection services)
{
    // ๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ ์ถ”๊ฐ€
    services.AddMemoryCache();
    
    // ์‘๋‹ต ์บ์‹ฑ ์ถ”๊ฐ€
    services.AddResponseCaching();
    
    // ์ปจํŠธ๋กค๋Ÿฌ ์„ค์ •
    services.AddControllers()
        .AddNewtonsoftJson();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ์‘๋‹ต ์บ์‹ฑ ๋ฏธ๋“ค์›จ์–ด ์‚ฌ์šฉ
    app.UseResponseCaching();
    
    // ๋‚˜๋จธ์ง€ ๋ฏธ๋“ค์›จ์–ด ์„ค์ •...
}

// ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์บ์‹ฑ ์ ์šฉ
[HttpGet]
[ResponseCache(Duration = 60)] // 60์ดˆ ๋™์•ˆ ์บ์‹ฑ
public async Task<ActionResult<List<ServiceDto>>> GetPopularServices()
{
    var cacheKey = "PopularServices";
    
    // ์บ์‹œ์—์„œ ๋ฐ์ดํ„ฐ ํ™•์ธ
    if (!_memoryCache.TryGetValue(cacheKey, out List<ServiceDto> services))
    {
        // ์บ์‹œ์— ์—†์œผ๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ
        services = await _repository.GetPopularServicesAsync();
        
        // ์บ์‹œ ์˜ต์…˜ ์„ค์ •
        var cacheOptions = new MemoryCacheEntryOptions()
            .SetAbsoluteExpiration(TimeSpan.FromMinutes(10))
            .SetPriority(CacheItemPriority.High);
        
        // ์บ์‹œ์— ์ €์žฅ
        _memoryCache.Set(cacheKey, services, cacheOptions);
    }
    
    return services;
}

๐Ÿ’ก ๋ณด์•ˆ ํŒ: API์—์„œ JSON ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋ณด์•ˆ์— ์ฃผ์˜ํ•ด์•ผ ํ•ด:

  1. ์ž…๋ ฅ ๊ฒ€์ฆ - ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ฐ›์€ JSON ๋ฐ์ดํ„ฐ๋Š” ํ•ญ์ƒ ๊ฒ€์ฆํ•ด์•ผ ํ•ด
  2. ๋ฏผ๊ฐํ•œ ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง - ์‘๋‹ต์—์„œ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋Š” ์ œ์™ธํ•˜๊ฑฐ๋‚˜ ๋งˆ์Šคํ‚น ์ฒ˜๋ฆฌ
  3. TypeNameHandling ์ฃผ์˜ - ์™ธ๋ถ€ ์†Œ์Šค์—์„œ ๋ฐ›์€ JSON์„ ์—ญ์ง๋ ฌํ™”ํ•  ๋•Œ TypeNameHandling.None ์‚ฌ์šฉ
  4. JSON ํ•˜์ด์žฌํ‚น ๋ฐฉ์ง€ - JSON ์‘๋‹ต์— ์ ์ ˆํ•œ Content-Type ํ—ค๋” ์„ค์ •

์žฌ๋Šฅ๋„ท๊ณผ ๊ฐ™์€ ์„œ๋น„์Šค ํ”Œ๋žซํผ์—์„œ๋Š” ๋‹ค์–‘ํ•œ API ์—”๋“œํฌ์ธํŠธ๋ฅผ ํ†ตํ•ด ์„œ๋น„์Šค ๋ชฉ๋ก, ์‚ฌ์šฉ์ž ์ •๋ณด, ๊ฒฐ์ œ ๋ฐ์ดํ„ฐ ๋“ฑ์„ JSON ํ˜•์‹์œผ๋กœ ์ฃผ๊ณ ๋ฐ›๊ฒŒ ๋ผ. JSON.NET์„ ํ™œ์šฉํ•˜๋ฉด ์ด๋Ÿฐ ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๊ตํ™˜์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์„œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด ํฌ๊ฒŒ ํ–ฅ์ƒ๋  ๊ฑฐ์•ผ! ๐ŸŒŸ

9. JSON.NET vs System.Text.Json ๋น„๊ต โš–๏ธ

์ตœ๊ทผ .NET Core 3.0๋ถ€ํ„ฐ Microsoft๋Š” System.Text.Json์ด๋ผ๋Š” ์ƒˆ๋กœ์šด JSON ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋„์ž…ํ–ˆ์–ด. ์ด ์„น์…˜์—์„œ๋Š” JSON.NET๊ณผ System.Text.Json์˜ ์ฐจ์ด์ ๊ณผ ๊ฐ๊ฐ์˜ ์žฅ๋‹จ์ ์„ ๋น„๊ตํ•ด๋ณผ ๊ฑฐ์•ผ! ๐Ÿ”

๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ• ๋น„๊ต ๐Ÿ“

๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•์„ ๋น„๊ตํ•ด๋ณด์ž:

// JSON.NET ์‚ฌ์šฉ ์˜ˆ
using Newtonsoft.Json;

// ์ง๋ ฌํ™”
string jsonNet = JsonConvert.SerializeObject(myObject, Formatting.Indented);

// ์—ญ์ง๋ ฌํ™”
MyClass objFromJsonNet = JsonConvert.DeserializeObject<MyClass>(jsonNet);

// System.Text.Json ์‚ฌ์šฉ ์˜ˆ
using System.Text.Json;

// ์ง๋ ฌํ™”
string systemJson = JsonSerializer.Serialize(myObject, new JsonSerializerOptions 
{ 
    WriteIndented = true 
});

// ์—ญ์ง๋ ฌํ™”
MyClass objFromSystemJson = JsonSerializer.Deserialize<MyClass>(systemJson);

์„ฑ๋Šฅ ๋น„๊ต โšก

์„ฑ๋Šฅ์€ ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋น„๊ตํ•  ๋•Œ ์ค‘์š”ํ•œ ์š”์†Œ์•ผ:

์„ฑ๋Šฅ ์ง€ํ‘œ JSON.NET System.Text.Json
์ง๋ ฌํ™” ์†๋„ ์ข‹์Œ ๋งค์šฐ ์ข‹์Œ (1.5~2๋ฐฐ ๋น ๋ฆ„)
์—ญ์ง๋ ฌํ™” ์†๋„ ์ข‹์Œ ๋งค์šฐ ์ข‹์Œ (1.3~1.8๋ฐฐ ๋น ๋ฆ„)
๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ๋ณดํ†ต ์ ์Œ (ํ• ๋‹น ์ตœ์†Œํ™”)
๋Œ€์šฉ๋Ÿ‰ JSON ์ฒ˜๋ฆฌ ์ข‹์Œ ๋งค์šฐ ์ข‹์Œ
JSON.NET vs System.Text.Json ๋น„๊ต ์„ฑ๋Šฅ ๋น„๊ต (์ƒ๋Œ€์  ์†๋„) ์ง๋ ฌํ™” JSON.NET System.Text.Json ์—ญ์ง๋ ฌํ™” JSON.NET System.Text.Json ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ JSON.NET System.Text.Json ๊ธฐ๋Šฅ ํ’๋ถ€๋„ JSON.NET (๋” ๋งŽ์€ ๊ธฐ๋Šฅ) System.Text.Json JSON.NET System.Text.Json

๊ธฐ๋Šฅ ๋น„๊ต ๐Ÿงฐ

๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ฃผ์š” ๊ธฐ๋Šฅ์„ ๋น„๊ตํ•ด๋ณด์ž:

๊ธฐ๋Šฅ JSON.NET System.Text.Json
LINQ to JSON โœ… ์ง€์› (JObject, JArray ๋“ฑ) โœ… ์ง€์› (JsonDocument, JsonElement)
JSON ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ โœ… ์ง€์› โŒ ๋ฏธ์ง€์›
๋™์  ํƒ€์ž… ์ง€์› โœ… ๋งค์šฐ ๊ฐ•๋ ฅ โš ๏ธ ์ œํ•œ์ 
์ปค์Šคํ…€ ์ปจ๋ฒ„ํ„ฐ โœ… ๋‹ค์–‘ํ•œ ์˜ต์…˜ โœ… ์ง€์› (๋‹ค๋ฅธ ๋ฐฉ์‹)
๋‹คํ˜•์„ฑ ์ฒ˜๋ฆฌ โœ… TypeNameHandling ์˜ต์…˜ โš ๏ธ ์ปค์Šคํ…€ ์ปจ๋ฒ„ํ„ฐ ํ•„์š”
์ˆœํ™˜ ์ฐธ์กฐ ์ฒ˜๋ฆฌ โœ… ReferenceLoopHandling ์˜ต์…˜ โœ… ReferenceHandler.Preserve
JSON ํŒจ์น˜ โœ… ์ง€์› โŒ ๋ฏธ์ง€์›
์ƒํƒœ๊ณ„ ๋ฐ ์„ฑ์ˆ™๋„ โœ… ๋งค์šฐ ์„ฑ์ˆ™ํ•จ โš ๏ธ ์ƒ๋Œ€์ ์œผ๋กœ ์ƒˆ๋กœ์›€

์ฝ”๋“œ ์˜ˆ์ œ ๋น„๊ต ๐Ÿงช

๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ฃผ์š” ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ๋น„๊ตํ•ด๋ณด์ž:

// 1. ๋ณต์žกํ•œ ๊ฐ์ฒด ์ง๋ ฌํ™”

// JSON.NET
var jsonNetSettings = new JsonSerializerSettings
{
    Formatting = Formatting.Indented,
    NullValueHandling = NullValueHandling.Ignore,
    ContractResolver = new CamelCasePropertyNamesContractResolver()
};
string jsonNetResult = JsonConvert.SerializeObject(myObject, jsonNetSettings);

// System.Text.Json
var systemJsonOptions = new JsonSerializerOptions
{
    WriteIndented = true,
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
string systemJsonResult = JsonSerializer.Serialize(myObject, systemJsonOptions);

// 2. ๋™์  JSON ์ฒ˜๋ฆฌ

// JSON.NET
JObject jsonNetObj = JObject.Parse(json);
string name = (string)jsonNetObj["person"]["name"];
int age = (int)jsonNetObj["person"]["age"];
JArray hobbies = (JArray)jsonNetObj["person"]["hobbies"];

// System.Text.Json
using JsonDocument doc = JsonDocument.Parse(json);
JsonElement root = doc.RootElement;
string name = root.GetProperty("person").GetProperty("name").GetString();
int age = root.GetProperty("person").GetProperty("age").GetInt32();
JsonElement hobbiesElement = root.GetProperty("person").GetProperty("hobbies");

์–ด๋–ค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ ํƒํ•ด์•ผ ํ• ๊นŒ? ๐Ÿค”

๊ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์žฅ๋‹จ์ ์„ ๊ณ ๋ คํ•˜์—ฌ ์„ ํƒํ•ด๋ณด์ž:

JSON.NET์„ ์„ ํƒํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ:

  1. ๋‹ค์–‘ํ•œ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•  ๋•Œ (JSON ์Šคํ‚ค๋งˆ, JSON ํŒจ์น˜ ๋“ฑ)
  2. ๋™์  ํƒ€์ž…๊ณผ ์œ ์—ฐํ•œ JSON ์ฒ˜๋ฆฌ๊ฐ€ ์ค‘์š”ํ•  ๋•Œ
  3. ๊ธฐ์กด ์ฝ”๋“œ๋ฒ ์ด์Šค๊ฐ€ JSON.NET์— ์˜์กดํ•˜๊ณ  ์žˆ์„ ๋•Œ
  4. ๋‹คํ˜•์„ฑ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ๋ณต์žกํ•œ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„๋ฅผ ๋‹ค๋ฃฐ ๋•Œ
  5. ํ’๋ถ€ํ•œ ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ์˜ต์…˜์ด ํ•„์š”ํ•  ๋•Œ

System.Text.Json์„ ์„ ํƒํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ:

  1. ์„ฑ๋Šฅ์ด ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์š”์†Œ์ผ ๋•Œ
  2. ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์ตœ์†Œํ™”ํ•ด์•ผ ํ•  ๋•Œ
  3. ์™ธ๋ถ€ ์ข…์†์„ฑ์„ ์ค„์ด๊ณ  ์‹ถ์„ ๋•Œ (.NET ๊ธฐ๋ณธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)
  4. ์ƒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•  ๋•Œ
  5. ๊ธฐ๋ณธ์ ์ธ JSON ์ฒ˜๋ฆฌ๋งŒ ํ•„์š”ํ•  ๋•Œ

๐Ÿ’ก ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒ: JSON.NET์—์„œ System.Text.Json์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋ ค๋ฉด ๋‹ค์Œ ์‚ฌํ•ญ์— ์ฃผ์˜ํ•ด์•ผ ํ•ด:

  1. ์†์„ฑ ์ด๋ฆ„ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์˜ ์ฐจ์ด (๊ธฐ๋ณธ๊ฐ’์ด ๋‹ค๋ฆ„)
  2. ๋‚ ์งœ ํ˜•์‹ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์˜ ์ฐจ์ด
  3. ๋™์  ํƒ€์ž… ๋ฐ ๋‹คํ˜•์„ฑ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์˜ ์ฐจ์ด
  4. ์ผ๋ถ€ ๊ธฐ๋Šฅ์€ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•  ์ˆ˜๋„ ์žˆ์Œ

์ ์ง„์  ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ์œ„ํ•ด ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์–ด!

์žฌ๋Šฅ๋„ท๊ณผ ๊ฐ™์€ ์„œ๋น„์Šค ํ”Œ๋žซํผ์„ ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์žฅ๋‹จ์ ์„ ์ž˜ ๊ณ ๋ คํ•ด์„œ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด. ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์™€ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•˜๋‹ค๋ฉด JSON.NET์ด ์—ฌ์ „ํžˆ ์ข‹์€ ์„ ํƒ์ด์ง€๋งŒ, ์„ฑ๋Šฅ์ด ์ค‘์š”ํ•˜๋‹ค๋ฉด System.Text.Json๋„ ๊ณ ๋ คํ•ด๋ณผ ๋งŒํ•ด! ๐Ÿš€

10. ๋งˆ๋ฌด๋ฆฌ ๋ฐ ์ถ”๊ฐ€ ์ž๋ฃŒ ๐Ÿ“š

์ง€๊ธˆ๊นŒ์ง€ JSON.NET ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ๊ณผ ํ™œ์šฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์–ด. ์ด์ œ JSON.NET์„ ํ™œ์šฉํ•ด C# ํ”„๋กœ์ ํŠธ์—์„œ JSON ๋ฐ์ดํ„ฐ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ! ๐ŸŽ‰

๋ฐฐ์šด ๋‚ด์šฉ ์š”์•ฝ ๐Ÿ“‹

  1. JSON๊ณผ JSON.NET ์†Œ๊ฐœ - JSON์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๊ณผ JSON.NET์˜ ์ฃผ์š” ํŠน์ง•
  2. ์„ค์น˜ ๋ฐ ๊ธฐ๋ณธ ์„ค์ • - NuGet์„ ํ†ตํ•œ ์„ค์น˜์™€ ๊ธฐ๋ณธ ์„ค์ • ๋ฐฉ๋ฒ•
  3. JSON ์ง๋ ฌํ™” - C# ๊ฐ์ฒด๋ฅผ JSON์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•
  4. JSON ์—ญ์ง๋ ฌํ™” - JSON์„ C# ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ธฐ๋ฒ•
  5. LINQ to JSON - ๋™์  JSON ๋ฐ์ดํ„ฐ๋ฅผ ์ฟผ๋ฆฌํ•˜๊ณ  ์กฐ์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•
  6. JSON ์Šคํ‚ค๋งˆ ๊ฒ€์ฆ - JSON ๋ฐ์ดํ„ฐ์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•˜๋Š” ๋ฐฉ๋ฒ•
  7. ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ๋ฐ ์„ฑ๋Šฅ ์ตœ์ ํ™” - ๋‹คํ˜•์„ฑ ์ฒ˜๋ฆฌ, ์ปค์Šคํ…€ ์ปจ๋ฒ„ํ„ฐ, ์„ฑ๋Šฅ ํ–ฅ์ƒ ๊ธฐ๋ฒ•
  8. ์›น API์™€ JSON.NET - ASP.NET Core์—์„œ JSON.NET ํ™œ์šฉํ•˜๊ธฐ
  9. JSON.NET vs System.Text.Json - ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋น„๊ต ๋ฐ ์„ ํƒ ๊ฐ€์ด๋“œ

JSON.NET ํ™œ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค ๐Ÿš€

JSON.NET์€ ๋‹ค์–‘ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด:

1. ์›น API ๊ฐœ๋ฐœ - ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๊ฐ„ ๋ฐ์ดํ„ฐ ๊ตํ™˜

2. ์„ค์ • ํŒŒ์ผ ๊ด€๋ฆฌ - ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ค์ •์„ JSON์œผ๋กœ ์ €์žฅํ•˜๊ณ  ๋กœ๋“œ

3. ๋ฐ์ดํ„ฐ ์ €์žฅ - NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‚˜ ํŒŒ์ผ ์‹œ์Šคํ…œ์— JSON ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ ์ €์žฅ

4. ์™ธ๋ถ€ API ํ†ตํ•ฉ - ๋‹ค์–‘ํ•œ ์™ธ๋ถ€ ์„œ๋น„์Šค์˜ JSON API ํ™œ์šฉ

5. ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ - ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํ˜•์‹ ๊ฐ„ ๋ณ€ํ™˜ ์ค‘๊ฐœ์ž๋กœ JSON ํ™œ์šฉ

JSON.NET ํ™œ์šฉ ์ƒํƒœ๊ณ„ JSON.NET Newtonsoft.Json ์›น API ๋ฐ์ดํ„ฐ ์ €์žฅ ์„ค์ • ๊ด€๋ฆฌ ์™ธ๋ถ€ API ํ†ตํ•ฉ ๋‹ค์–‘ํ•œ C# ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ JSON ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์˜ ์ค‘์‹ฌ

์ถ”๊ฐ€ ํ•™์Šต ์ž๋ฃŒ ๐Ÿ“š

JSON.NET์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ ์ž๋ฃŒ๋ฅผ ์ฐธ๊ณ ํ•ด๋ด:

  1. ๊ณต์‹ ๋ฌธ์„œ - Newtonsoft.Json ๊ณต์‹ ๋ฌธ์„œ
  2. GitHub ์ €์žฅ์†Œ - JSON.NET GitHub
  3. NuGet ํŒจํ‚ค์ง€ - Newtonsoft.Json NuGet
  4. JSON ์Šคํ‚ค๋งˆ - JSON ์Šคํ‚ค๋งˆ ๊ณต์‹ ์‚ฌ์ดํŠธ
  5. Microsoft ๋ฌธ์„œ - System.Text.Json ๋น„๊ต ๋ฌธ์„œ

๋งˆ๋ฌด๋ฆฌ ์ƒ๊ฐ ๐Ÿ’ญ

JSON.NET์€ C# ๊ฐœ๋ฐœ์ž์—๊ฒŒ JSON ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์•ผ. ์›น API, ๋ฐ์ดํ„ฐ ์ €์žฅ, ์„ค์ • ๊ด€๋ฆฌ ๋“ฑ ๋‹ค์–‘ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์ง€. ํŠนํžˆ ์žฌ๋Šฅ๋„ท๊ณผ ๊ฐ™์€ ์„œ๋น„์Šค ํ”Œ๋žซํผ์„ ๊ฐœ๋ฐœํ•  ๋•Œ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ, ์„œ๋น„์Šค ์ •๋ณด, ๊ฒฐ์ œ ๋‚ด์—ญ ๋“ฑ์„ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋  ๊ฑฐ์•ผ.

์ตœ๊ทผ์—๋Š” System.Text.Json์ด๋ผ๋Š” ๋Œ€์•ˆ์ด ๋“ฑ์žฅํ–ˆ์ง€๋งŒ, JSON.NET์˜ ํ’๋ถ€ํ•œ ๊ธฐ๋Šฅ๊ณผ ์œ ์—ฐ์„ฑ์€ ์—ฌ์ „ํžˆ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ์„ ํ˜ธํ•˜๋Š” ์ด์œ ์•ผ. ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์žฅ๋‹จ์ ์„ ์ดํ•ดํ•˜๊ณ  ํ”„๋กœ์ ํŠธ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๊ฒŒ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด.

์ด ๊ธ€์ด JSON.NET์„ ์ดํ•ดํ•˜๊ณ  ํ™œ์šฉํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜์—ˆ๊ธธ ๋ฐ”๋ผ! ๊ถ๊ธˆํ•œ ์ ์ด ์žˆ๊ฑฐ๋‚˜ ๋” ์•Œ๊ณ  ์‹ถ์€ ๋‚ด์šฉ์ด ์žˆ๋‹ค๋ฉด ์žฌ๋Šฅ๋„ท์˜ ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์งˆ๋ฌธํ•ด๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ. ๋‹ค์–‘ํ•œ ๊ฐœ๋ฐœ์ž๋“ค์˜ ๊ฒฝํ—˜๊ณผ ์ง€์‹์„ ๊ณต์œ ๋ฐ›์„ ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ! ๐Ÿ˜Š

JSON.NET์œผ๋กœ ๋” ๋‚˜์€ C# ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค์–ด๋ณด์„ธ์š”!

์žฌ๋Šฅ๋„ท์—์„œ JSON.NET ๊ด€๋ จ ์งˆ๋ฌธ์ด๋‚˜ ํ”„๋กœ์ ํŠธ ๋„์›€์„ ๋ฐ›์•„๋ณด์„ธ์š”. ๋‹ค์–‘ํ•œ ๊ฐœ๋ฐœ ์ „๋ฌธ๊ฐ€๋“ค์ด ์—ฌ๋Ÿฌ๋ถ„์˜ ๋ฌธ์ œ ํ•ด๊ฒฐ์„ ๋„์™€๋“œ๋ฆฝ๋‹ˆ๋‹ค.

๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.