Ver2.0 ๐ JSON.NET ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก JSON ๋ง์คํฐํ๊ธฐ: C# ๊ฐ๋ฐ์๋ฅผ ์ํ ์๋ฒฝ ๊ฐ์ด๋ ๐

๐ JSON.NET ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก JSON ๋ง์คํฐํ๊ธฐ: C# ๊ฐ๋ฐ์๋ฅผ ์ํ ์๋ฒฝ ๊ฐ์ด๋ ๐
C# ๊ฐ๋ฐ์๋ผ๋ฉด ๊ผญ ์์์ผ ํ JSON ์ฒ๋ฆฌ์ ๋ชจ๋ ๊ฒ!
์๋ ? ์ค๋์ C# ๊ฐ๋ฐ์๋ผ๋ฉด ๋ฐ๋์ ์์์ผ ํ JSON.NET(Newtonsoft.Json) ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํด ํจ๊ป ์์๋ณผ ๊ฑฐ์ผ. JSON์ ํ๋ ์น ๊ฐ๋ฐ์์ ๋ฐ์ดํฐ ๊ตํ ํ์์ ํ์ค์ด ๋์๊ณ , C#์์ ์ด๋ฅผ ๋ค๋ฃจ๋ ๊ฐ์ฅ ๊ฐ๋ ฅํ ๋๊ตฌ๊ฐ ๋ฐ๋ก JSON.NET์ด์ง! ๐
์ด ๊ธ์ ํตํด JSON.NET์ ๊ธฐ๋ณธ๋ถํฐ ๊ณ ๊ธ ๊ธฐ๋ฅ๊น์ง ๋ชจ๋ ๋ง์คํฐํ ์ ์์ ๊ฑฐ์ผ. ํนํ ์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์ ๊ฐ๋ฐํ ๋๋ ์ฌ์ฉ์ ํ๋กํ, ์๋น์ค ์ ๋ณด, API ์๋ต ๋ฑ์ JSON์ผ๋ก ์ฃผ๊ณ ๋ฐ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ผ๋ ์ค๋ฌด์ ๋ฐ๋ก ์ ์ฉํ ์ ์๋ ์ง์์ด ๋ ๊ฑฐ์ผ! ๊ทธ๋ผ ์์ํด๋ณผ๊น? ๐
๐ ๋ชฉ์ฐจ
- JSON๊ณผ JSON.NET ์๊ฐ
- JSON.NET ์ค์น ๋ฐ ๊ธฐ๋ณธ ์ค์
- JSON ์ง๋ ฌํ(Serialization) ๋ง์คํฐํ๊ธฐ
- JSON ์ญ์ง๋ ฌํ(Deserialization) ์๋ฒฝ ์ดํด
- LINQ to JSON์ผ๋ก ๋์ ๋ฐ์ดํฐ ๋ค๋ฃจ๊ธฐ
- JSON ์คํค๋ง ๊ฒ์ฆํ๊ธฐ
- ๊ณ ๊ธ ๊ธฐ๋ฅ ๋ฐ ์ฑ๋ฅ ์ต์ ํ
- ์ค์ ์์ : ์น API์ JSON.NET
- JSON.NET vs System.Text.Json ๋น๊ต
- ๋ง๋ฌด๋ฆฌ ๋ฐ ์ถ๊ฐ ์๋ฃ
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์ ์ฃผ์ ํน์ง โจ
- ๊ฐ๋ ฅํ ์ง๋ ฌํ/์ญ์ง๋ ฌํ - ๋ณต์กํ .NET ๊ฐ์ฒด๋ JSON์ผ๋ก ์ฝ๊ฒ ๋ณํ
- LINQ to JSON - JSON ๋ฐ์ดํฐ๋ฅผ LINQ๋ก ์ฟผ๋ฆฌํ๋ ๊ธฐ๋ฅ
- ์คํค๋ง ๊ฒ์ฆ - JSON ์คํค๋ง๋ฅผ ํตํ ๋ฐ์ดํฐ ์ ํจ์ฑ ๊ฒ์ฌ
- ๊ณ ์ฑ๋ฅ - ์ต์ ํ๋ ์ฑ๋ฅ์ผ๋ก ๋์ฉ๋ 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; }
}
์กฐ๊ฑด๋ถ ์ง๋ ฌํ ๐
ํน์ ์กฐ๊ฑด์ ๋ฐ๋ผ ์์ฑ์ ์ง๋ ฌํํ ์ง ๊ฒฐ์ ํ๊ณ ์ถ๋ค๋ฉด 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}์");
์ปค์คํ ๋ณํ๊ธฐ(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);
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.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);
}
}
}
}
์ปค์คํ 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์ ์ฑ๋ฅ์ ์ธก์ ํ๊ณ ์ต์ ํํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๋๊ตฌ๋ฅผ ํ์ฉํด ๋ณด์ธ์:
- BenchmarkDotNet - ๋ค์ํ ์ง๋ ฌํ/์ญ์ง๋ ฌํ ๋ฐฉ๋ฒ์ ์ฑ๋ฅ ๋น๊ต
- dotMemory - ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๋ถ์
- 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 ์๋ต ํ์ ํ์คํํ๊ธฐ ๐
์ผ๊ด๋ 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 ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ๋ ๋ณด์์ ์ฃผ์ํด์ผ ํด:
- ์ ๋ ฅ ๊ฒ์ฆ - ํด๋ผ์ด์ธํธ์์ ๋ฐ์ JSON ๋ฐ์ดํฐ๋ ํญ์ ๊ฒ์ฆํด์ผ ํด
- ๋ฏผ๊ฐํ ๋ฐ์ดํฐ ํํฐ๋ง - ์๋ต์์ ๋ฏผ๊ฐํ ์ ๋ณด๋ ์ ์ธํ๊ฑฐ๋ ๋ง์คํน ์ฒ๋ฆฌ
- TypeNameHandling ์ฃผ์ - ์ธ๋ถ ์์ค์์ ๋ฐ์ JSON์ ์ญ์ง๋ ฌํํ ๋ TypeNameHandling.None ์ฌ์ฉ
- 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 | 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์ ์ ํํด์ผ ํ๋ ๊ฒฝ์ฐ:
- ๋ค์ํ ๊ณ ๊ธ ๊ธฐ๋ฅ์ด ํ์ํ ๋ (JSON ์คํค๋ง, JSON ํจ์น ๋ฑ)
- ๋์ ํ์ ๊ณผ ์ ์ฐํ JSON ์ฒ๋ฆฌ๊ฐ ์ค์ํ ๋
- ๊ธฐ์กด ์ฝ๋๋ฒ ์ด์ค๊ฐ JSON.NET์ ์์กดํ๊ณ ์์ ๋
- ๋คํ์ฑ ์ฒ๋ฆฌ๊ฐ ํ์ํ ๋ณต์กํ ๊ฐ์ฒด ๊ทธ๋ํ๋ฅผ ๋ค๋ฃฐ ๋
- ํ๋ถํ ์ปค์คํฐ๋ง์ด์ง ์ต์ ์ด ํ์ํ ๋
System.Text.Json์ ์ ํํด์ผ ํ๋ ๊ฒฝ์ฐ:
- ์ฑ๋ฅ์ด ๊ฐ์ฅ ์ค์ํ ์์์ผ ๋
- ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ต์ํํด์ผ ํ ๋
- ์ธ๋ถ ์ข ์์ฑ์ ์ค์ด๊ณ ์ถ์ ๋ (.NET ๊ธฐ๋ณธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ)
- ์ ํ๋ก์ ํธ๋ฅผ ์์ํ ๋
- ๊ธฐ๋ณธ์ ์ธ JSON ์ฒ๋ฆฌ๋ง ํ์ํ ๋
๐ก ๋ง์ด๊ทธ๋ ์ด์ ํ: JSON.NET์์ System.Text.Json์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๋ ค๋ฉด ๋ค์ ์ฌํญ์ ์ฃผ์ํด์ผ ํด:
- ์์ฑ ์ด๋ฆ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ฐจ์ด (๊ธฐ๋ณธ๊ฐ์ด ๋ค๋ฆ)
- ๋ ์ง ํ์ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ฐจ์ด
- ๋์ ํ์ ๋ฐ ๋คํ์ฑ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ฐจ์ด
- ์ผ๋ถ ๊ธฐ๋ฅ์ ์ง์ ๊ตฌํํด์ผ ํ ์๋ ์์
์ ์ง์ ๋ง์ด๊ทธ๋ ์ด์ ์ ์ํด ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํจ๊ป ์ฌ์ฉํ ์๋ ์์ด!
์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ์๋น์ค ํ๋ซํผ์ ๊ฐ๋ฐํ ๋๋ ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฅ๋จ์ ์ ์ ๊ณ ๋ คํด์ ์ ํํ๋ ๊ฒ์ด ์ค์ํด. ๋ณต์กํ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ๋ค์ํ ๊ธฐ๋ฅ์ด ํ์ํ๋ค๋ฉด JSON.NET์ด ์ฌ์ ํ ์ข์ ์ ํ์ด์ง๋ง, ์ฑ๋ฅ์ด ์ค์ํ๋ค๋ฉด System.Text.Json๋ ๊ณ ๋ คํด๋ณผ ๋งํด! ๐
10. ๋ง๋ฌด๋ฆฌ ๋ฐ ์ถ๊ฐ ์๋ฃ ๐
์ง๊ธ๊น์ง JSON.NET ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ค์ํ ๊ธฐ๋ฅ๊ณผ ํ์ฉ๋ฒ์ ๋ํด ์์๋ดค์ด. ์ด์ JSON.NET์ ํ์ฉํด C# ํ๋ก์ ํธ์์ JSON ๋ฐ์ดํฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๋ค๋ฃฐ ์ ์์ ๊ฑฐ์ผ! ๐
๋ฐฐ์ด ๋ด์ฉ ์์ฝ ๐
- JSON๊ณผ JSON.NET ์๊ฐ - JSON์ ๊ธฐ๋ณธ ๊ฐ๋ ๊ณผ JSON.NET์ ์ฃผ์ ํน์ง
- ์ค์น ๋ฐ ๊ธฐ๋ณธ ์ค์ - NuGet์ ํตํ ์ค์น์ ๊ธฐ๋ณธ ์ค์ ๋ฐฉ๋ฒ
- JSON ์ง๋ ฌํ - C# ๊ฐ์ฒด๋ฅผ JSON์ผ๋ก ๋ณํํ๋ ๋ค์ํ ๋ฐฉ๋ฒ
- JSON ์ญ์ง๋ ฌํ - JSON์ C# ๊ฐ์ฒด๋ก ๋ณํํ๋ ๊ธฐ๋ฒ
- LINQ to JSON - ๋์ JSON ๋ฐ์ดํฐ๋ฅผ ์ฟผ๋ฆฌํ๊ณ ์กฐ์ํ๋ ๋ฐฉ๋ฒ
- JSON ์คํค๋ง ๊ฒ์ฆ - JSON ๋ฐ์ดํฐ์ ์ ํจ์ฑ์ ๊ฒ์ฌํ๋ ๋ฐฉ๋ฒ
- ๊ณ ๊ธ ๊ธฐ๋ฅ ๋ฐ ์ฑ๋ฅ ์ต์ ํ - ๋คํ์ฑ ์ฒ๋ฆฌ, ์ปค์คํ ์ปจ๋ฒํฐ, ์ฑ๋ฅ ํฅ์ ๊ธฐ๋ฒ
- ์น API์ JSON.NET - ASP.NET Core์์ JSON.NET ํ์ฉํ๊ธฐ
- 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์ ๋ํด ๋ ์์ธํ ์์๋ณด๊ณ ์ถ๋ค๋ฉด ๋ค์ ์๋ฃ๋ฅผ ์ฐธ๊ณ ํด๋ด:
- ๊ณต์ ๋ฌธ์ - Newtonsoft.Json ๊ณต์ ๋ฌธ์
- GitHub ์ ์ฅ์ - JSON.NET GitHub
- NuGet ํจํค์ง - Newtonsoft.Json NuGet
- JSON ์คํค๋ง - JSON ์คํค๋ง ๊ณต์ ์ฌ์ดํธ
- Microsoft ๋ฌธ์ - System.Text.Json ๋น๊ต ๋ฌธ์
๋ง๋ฌด๋ฆฌ ์๊ฐ ๐ญ
JSON.NET์ C# ๊ฐ๋ฐ์์๊ฒ JSON ์ฒ๋ฆฌ๋ฅผ ์ํ ๊ฐ๋ ฅํ ๋๊ตฌ์ผ. ์น API, ๋ฐ์ดํฐ ์ ์ฅ, ์ค์ ๊ด๋ฆฌ ๋ฑ ๋ค์ํ ์๋๋ฆฌ์ค์์ ํ์ฉํ ์ ์์ง. ํนํ ์ฌ๋ฅ๋ท๊ณผ ๊ฐ์ ์๋น์ค ํ๋ซํผ์ ๊ฐ๋ฐํ ๋ ์ฌ์ฉ์ ๋ฐ์ดํฐ, ์๋น์ค ์ ๋ณด, ๊ฒฐ์ ๋ด์ญ ๋ฑ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ ๋ฐ ํฐ ๋์์ด ๋ ๊ฑฐ์ผ.
์ต๊ทผ์๋ System.Text.Json์ด๋ผ๋ ๋์์ด ๋ฑ์ฅํ์ง๋ง, JSON.NET์ ํ๋ถํ ๊ธฐ๋ฅ๊ณผ ์ ์ฐ์ฑ์ ์ฌ์ ํ ๋ง์ ๊ฐ๋ฐ์๋ค์ด ์ ํธํ๋ ์ด์ ์ผ. ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฅ๋จ์ ์ ์ดํดํ๊ณ ํ๋ก์ ํธ ์๊ตฌ์ฌํญ์ ๋ง๊ฒ ์ ํํ๋ ๊ฒ์ด ์ค์ํด.
์ด ๊ธ์ด JSON.NET์ ์ดํดํ๊ณ ํ์ฉํ๋ ๋ฐ ๋์์ด ๋์๊ธธ ๋ฐ๋ผ! ๊ถ๊ธํ ์ ์ด ์๊ฑฐ๋ ๋ ์๊ณ ์ถ์ ๋ด์ฉ์ด ์๋ค๋ฉด ์ฌ๋ฅ๋ท์ ์ปค๋ฎค๋ํฐ์์ ์ง๋ฌธํด๋ณด๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ด์ผ. ๋ค์ํ ๊ฐ๋ฐ์๋ค์ ๊ฒฝํ๊ณผ ์ง์์ ๊ณต์ ๋ฐ์ ์ ์์ ๊ฑฐ์ผ! ๐
JSON.NET์ผ๋ก ๋ ๋์ C# ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค์ด๋ณด์ธ์!
์ฌ๋ฅ๋ท์์ JSON.NET ๊ด๋ จ ์ง๋ฌธ์ด๋ ํ๋ก์ ํธ ๋์์ ๋ฐ์๋ณด์ธ์. ๋ค์ํ ๊ฐ๋ฐ ์ ๋ฌธ๊ฐ๋ค์ด ์ฌ๋ฌ๋ถ์ ๋ฌธ์ ํด๊ฒฐ์ ๋์๋๋ฆฝ๋๋ค.
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.