언어
이 문서에서는 System.Text.Json 네임스페이스를 사용하여 오버플로 JSON을 처리하는 방법을 보여줍니다. 또한 대상 형식이 역직렬화되는 모든 JSON과 완벽하게 일치하지 않을 수 있는 다른 시나리오의 대안으로 JsonElement 또는 JsonNode로 역직렬화하는 방법도 보여줍니다.
오버플로 JSON 처리
역직렬화할 때 대상 형식의 속성으로 표시되지 않는 데이터를 JSON에서 받을 수 있습니다. 예를 들어 대상 형식이 다음과 같다고 가정하겠습니다.
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
Public Class WeatherForecast
Public Property [Date] As DateTimeOffset
Public Property TemperatureCelsius As Integer
Public Property Summary As String
End Class
그리고 역직렬화할 JSON은 다음과 같습니다.
{
"Date": "2019-08-01T00:00:00-07:00",
"temperatureCelsius": 25,
"Summary": "Hot",
"DatesAvailable": [
"2019-08-01T00:00:00-07:00",
"2019-08-02T00:00:00-07:00"
],
"SummaryWords": [
"Cool",
"Windy",
"Humid"
]
}
표시된 JSON을 표시된 형식으로 역직렬화하면 DatesAvailable 및 SummaryWords 속성은 이동할 곳이 없으므로 없어집니다. 이러한 속성과 같은 추가 데이터를 캡처하려면 [JsonExtensionData] 특성을 속성 또는 필드에 적용합니다. 다음 지원되는 선언 중 하나를 사용합니다.
- 확장 데이터 멤버를 .로 JsonObject선언합니다.
- 확장 데이터 멤버를 .로
IDictionary<string, object>선언합니다. - 확장 데이터 멤버를 .로
IDictionary<string, JsonElement>선언합니다. - .NET 11 이상에서와 같이
IReadOnlyDictionary<string, object>확장 데이터 멤버를 선언합니다. - .NET 11 이상에서와 같이
IReadOnlyDictionary<string, JsonElement>확장 데이터 멤버를 선언합니다.
변경 가능한 사전 확장 데이터의 경우 지원되는 IDictionary 인터페이스 중 하나에 할당할 수 있는 모든 형식(예: Dictionary<string, JsonElement>.)을 사용합니다. 읽기 전용 선언은 위에 나열된 정확한 IReadOnlyDictionary 인터페이스 형식 중 하나를 사용해야 합니다.
public class WeatherForecastWithExtensionData
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement>? ExtensionData { get; set; }
}
Public Class WeatherForecastWithExtensionData
Public Property [Date] As DateTimeOffset
Public Property TemperatureCelsius As Integer
Public Property Summary As String
<JsonExtensionData>
Public Property ExtensionData As Dictionary(Of String, Object)
End Class
확장 데이터 멤버의 IReadOnlyDictionary 경우 .NET 11은 a Dictionary<string, object> 또는 Dictionary<string, JsonElement>.를 구체화합니다. 직렬 변환기가 기존 값으로 새 사전을 초기화한 다음 그 멤버에 다시 할당하므로, 해당 멤버는 쓰기 가능해야 합니다. 들어오는 JSON 속성이 기존 키를 복제하면 들어오는 값이 우선합니다.
다음 표에서는 이전에 표시된 JSON을 이 샘플 형식으로 역직렬화한 결과를 보여줍니다. 추가 데이터는 ExtensionData 속성의 키-값 쌍이 됩니다.
| 속성 | 값 | 참고 사항 |
|---|---|---|
Date |
"8/1/2019 12:00:00 AM -07:00" |
|
TemperatureCelsius |
0 |
대/소문자를 구분하는 불일치(JSON의 temperatureCelsius). 따라서 속성이 설정되지 않습니다. |
Summary |
"Hot" |
|
ExtensionData |
"temperatureCelsius": 25,"DatesAvailable": ["2019-08-01T00:00:00-07:00","2019-08-02T00:00:00-07:00"],"SummaryWords": ["Cool","Windy","Humid"] |
대/소문자가 일치하지 않으므로 temperatureCelsius는 여분 항목이며 사전에서 키-값 쌍으로 처리됩니다. JSON의 추가 배열은 각각 키-값 쌍이 되고, 배열은 값 개체로 사용됩니다. |
대상 개체가 직렬화되면 확장 데이터 키 값 쌍은 마치 수신 JSON에 있는 것처럼 JSON 속성이 됩니다.
{
"Date": "2019-08-01T00:00:00-07:00",
"TemperatureCelsius": 0,
"Summary": "Hot",
"temperatureCelsius": 25,
"DatesAvailable": [
"2019-08-01T00:00:00-07:00",
"2019-08-02T00:00:00-07:00"
],
"SummaryWords": [
"Cool",
"Windy",
"Humid"
]
}
ExtensionData 속성 이름은 JSON에 표시되지 않습니다. 이 동작을 통해 JSON은 추가 데이터를 잃지 않고도 라운드트립을 수행할 수 있으며, 이 동작이 없으면 추가 데이터가 역직렬화되지 않습니다.
.NET 11부터 serialization은 JsonObject 확장 데이터를 포함하는 JSON 개체로 평면화합니다. 속성은 JsonObject 확장 데이터 멤버 이름이 아니라 포함하는 개체에 직접 표시됩니다.
다음 예제에서는 JSON에서 역직렬화된 개체로 이동해 다시 JSON으로 복귀하는 왕복을 보여줍니다.
using System.Text.Json;
using System.Text.Json.Serialization;
namespace RoundtripExtensionData
{
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement>? ExtensionData { get; set; }
}
public class Program
{
public static void Main()
{
string jsonString =
@"{
""Date"": ""2019-08-01T00:00:00-07:00"",
""temperatureCelsius"": 25,
""Summary"": ""Hot"",
""SummaryField"": ""Hot"",
""DatesAvailable"": [
""2019-08-01T00:00:00-07:00"",
""2019-08-02T00:00:00-07:00""
],
""SummaryWords"": [
""Cool"",
""Windy"",
""Humid""
]
}";
WeatherForecast weatherForecast =
JsonSerializer.Deserialize<WeatherForecast>(jsonString)!;
var serializeOptions = new JsonSerializerOptions { WriteIndented = true };
jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);
Console.WriteLine($"JSON output:\n{jsonString}\n");
}
}
}
// output:
//JSON output:
//{
// "Date": "2019-08-01T00:00:00-07:00",
// "TemperatureCelsius": 0,
// "Summary": "Hot",
// "temperatureCelsius": 25,
// "SummaryField": "Hot",
// "DatesAvailable": [
// "2019-08-01T00:00:00-07:00",
// "2019-08-02T00:00:00-07:00"
// ],
// "SummaryWords": [
// "Cool",
// "Windy",
// "Humid"
// ]
//}
JsonElement 또는 JsonNode로 역직렬화
특정 속성에 대해 허용되는 JSON을 유연하게 사용하려는 경우 JsonElement 또는 JsonNode로 역직렬화하는 것이 대안입니다. 유효한 JSON 속성은 JsonElement 또는 JsonNode로 역직렬화할 수 있습니다. 변경할 수 없는 개체를 만들거나 JsonElement 변경 가능한 개체를 만들도록 선택합니다JsonNode.
다음 예제에서는 형식 JsonElement 및 JsonNode의 속성을 포함하는 클래스에 대해 JSON에서 출발해 JSON으로 복귀하는 왕복을 보여줍니다.
using System.Text.Json;
using System.Text.Json.Nodes;
namespace RoundtripJsonElementAndNode
{
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
public JsonElement DatesAvailable { get; set; }
public JsonNode? SummaryWords { get; set; }
}
public class Program
{
public static void Main()
{
string jsonString =
@"{
""Date"": ""2019-08-01T00:00:00-07:00"",
""TemperatureCelsius"": 25,
""Summary"": ""Hot"",
""DatesAvailable"": [
""2019-08-01T00:00:00-07:00"",
""2019-08-02T00:00:00-07:00""
],
""SummaryWords"": [
""Cool"",
""Windy"",
""Humid""
]
}";
WeatherForecast? weatherForecast =
JsonSerializer.Deserialize<WeatherForecast>(jsonString);
var serializeOptions = new JsonSerializerOptions { WriteIndented = true };
jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);
Console.WriteLine(jsonString);
}
}
}
// output:
//{
// "Date": "2019-08-01T00:00:00-07:00",
// "TemperatureCelsius": 25,
// "Summary": "Hot",
// "DatesAvailable": [
// "2019-08-01T00:00:00-07:00",
// "2019-08-02T00:00:00-07:00"
// ],
// "SummaryWords": [
// "Cool",
// "Windy",
// "Humid"
// ]
//}
참고 항목
.NET