Menggunakan jenis dan properti yang tidak dapat diubah
Jenis yang tidak dapat diubah adalah jenis yang mencegah Anda mengubah nilai properti atau bidang objek apa pun setelah dibuat. Jenisnya mungkin rekaman, tidak memiliki properti atau bidang publik, memiliki properti baca-saja, atau memiliki properti dengan setter privat atau init-saja. System.String adalah contoh jenis yang tidak dapat diubah. System.Text.Json menyediakan berbagai cara agar Anda dapat mendeserialisasi JSON ke jenis yang tidak dapat diubah.
Konstruktor berparameter
Secara default, System.Text.Json
menggunakan konstruktor tanpa parameter publik default. Namun, Anda dapat memberi tahunya untuk menggunakan konstruktor berparameter, yang memungkinkan untuk mendeserialisasi kelas atau struct yang tidak dapat diubah.
Untuk kelas, jika satu-satunya konstruktor adalah konstruktor berparameter, konstruktor tersebut akan digunakan.
Untuk struktur atau kelas dengan beberapa konstruktor, tentukan yang akan digunakan dengan menerapkan atribut [JsonConstructor]. Ketika atribut tidak digunakan, konstruktor tanpa parameter publik selalu digunakan jika ada.
Contoh berikut menggunakan
[JsonConstructor]
atribut:using System.Text.Json; using System.Text.Json.Serialization; namespace ImmutableTypes { public struct Forecast { public DateTime Date { get; } public int TemperatureC { get; } public string Summary { get; } [JsonConstructor] public Forecast(DateTime date, int temperatureC, string summary) => (Date, TemperatureC, Summary) = (date, temperatureC, summary); } public class Program { public static void Main() { string json = """ { "date":"2020-09-06T11:31:01.923395-07:00", "temperatureC":-1, "summary":"Cold" } """; Console.WriteLine($"Input JSON: {json}"); var options = JsonSerializerOptions.Web; Forecast forecast = JsonSerializer.Deserialize<Forecast>(json, options); Console.WriteLine($"forecast.Date: {forecast.Date}"); Console.WriteLine($"forecast.TemperatureC: {forecast.TemperatureC}"); Console.WriteLine($"forecast.Summary: {forecast.Summary}"); string roundTrippedJson = JsonSerializer.Serialize<Forecast>(forecast, options); Console.WriteLine($"Output JSON: {roundTrippedJson}"); } } } // Produces output like the following example: // //Input JSON: { "date":"2020-09-06T11:31:01.923395-07:00","temperatureC":-1,"summary":"Cold"} //forecast.Date: 9 / 6 / 2020 11:31:01 AM //forecast.TemperatureC: -1 //forecast.Summary: Cold //Output JSON: { "date":"2020-09-06T11:31:01.923395-07:00","temperatureC":-1,"summary":"Cold"}
Imports System.Text.Json Imports System.Text.Json.Serialization Namespace ImmutableTypes Public Structure Forecast Public ReadOnly Property [Date] As Date Public ReadOnly Property TemperatureC As Integer Public ReadOnly Property Summary As String <JsonConstructor> Public Sub New([Date] As Date, TemperatureC As Integer, Summary As String) Me.Date = [Date] Me.TemperatureC = TemperatureC Me.Summary = Summary End Sub End Structure Public NotInheritable Class Program Public Shared Sub Main() Dim json As String = "{""date"":""2020-09-06T11:31:01.923395-07:00"",""temperatureC"":-1,""summary"":""Cold""}" Console.WriteLine($"Input JSON: {json}") Dim forecast1 As Forecast = JsonSerializer.Deserialize(Of Forecast)(json, JsonSerializerOptions.Web) Console.WriteLine($"forecast.Date: {forecast1.[Date]}") Console.WriteLine($"forecast.TemperatureC: {forecast1.TemperatureC}") Console.WriteLine($"forecast.Summary: {forecast1.Summary}") Dim roundTrippedJson As String = JsonSerializer.Serialize(forecast1, JsonSerializerOptions.Web) Console.WriteLine($"Output JSON: {roundTrippedJson}") End Sub End Class End Namespace ' Produces output like the following example: ' 'Input JSON: { "date":"2020-09-06T11:31:01.923395-07:00","temperatureC":-1,"summary":"Cold"} 'forecast.Date: 9 / 6 / 2020 11:31:01 AM 'forecast.TemperatureC: -1 'forecast.Summary: Cold 'Output JSON: { "date":"2020-09-06T11:31:01.923395-07:00","temperatureC":-1,"summary":"Cold"}
Dalam .NET 7 dan versi yang lebih lama,
[JsonConstructor]
atribut hanya dapat digunakan dengan konstruktor publik.
Nama parameter konstruktor berparameter harus cocok dengan nama dan jenis properti. Pencocokan tidak peka huruf besar/kecil, dan parameter konstruktor harus cocok dengan nama properti aktual meskipun Anda menggunakan [JsonPropertyName] untuk mengganti nama properti. Dalam contoh berikut, nama untuk TemperatureC
properti diubah menjadi celsius
pada JSON, tetapi parameter konstruktor masih bernama temperatureC
:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ImmutableTypesCtorParms
{
public readonly struct Forecast
{
public DateTime Date { get; }
[JsonPropertyName("celsius")]
public int TemperatureC { get; }
public string Summary { get; }
[JsonConstructor]
public Forecast(DateTime date, int temperatureC, string summary) =>
(Date, TemperatureC, Summary) = (date, temperatureC, summary);
}
public class Program
{
public static void Main()
{
string json = """
{
"date":"2020-09-06T11:31:01.923395-07:00",
"celsius":-1,
"summary":"Cold"
}
""";
Console.WriteLine($"Input JSON: {json}");
var options = JsonSerializerOptions.Web;
Forecast forecast = JsonSerializer.Deserialize<Forecast>(json, options);
Console.WriteLine($"forecast.Date: {forecast.Date}");
Console.WriteLine($"forecast.TemperatureC: {forecast.TemperatureC}");
Console.WriteLine($"forecast.Summary: {forecast.Summary}");
string roundTrippedJson =
JsonSerializer.Serialize<Forecast>(forecast, options);
Console.WriteLine($"Output JSON: {roundTrippedJson}");
}
}
}
// Produces output like the following example:
//
//Input JSON: { "date":"2020-09-06T11:31:01.923395-07:00","celsius":-1,"summary":"Cold"}
//forecast.Date: 9 / 6 / 2020 11:31:01 AM
//forecast.TemperatureC: -1
//forecast.Summary: Cold
//Output JSON: { "date":"2020-09-06T11:31:01.923395-07:00","celsius":-1,"summary":"Cold"}
[JsonPropertyName]
Selain itu , atribut berikut mendukung deserialisasi dengan konstruktor berparameter:
Data
Rekaman juga didukung untuk serialisasi dan deserialisasi, seperti yang ditunjukkan dalam contoh berikut:
using System.Text.Json;
namespace Records
{
public record Forecast(DateTime Date, int TemperatureC)
{
public string? Summary { get; init; }
};
public class Program
{
public static void Main()
{
Forecast forecast = new(DateTime.Now, 40)
{
Summary = "Hot!"
};
string forecastJson = JsonSerializer.Serialize<Forecast>(forecast);
Console.WriteLine(forecastJson);
Forecast? forecastObj = JsonSerializer.Deserialize<Forecast>(forecastJson);
Console.WriteLine(forecastObj);
}
}
}
// Produces output like the following example:
//
//{ "Date":"2020-10-21T15:26:10.5044594-07:00","TemperatureC":40,"Summary":"Hot!"}
//Forecast { Date = 10 / 21 / 2020 3:26:10 PM, TemperatureC = 40, Summary = Hot! }
Anda dapat menerapkan salah satu atribut ke nama properti menggunakan property:
target pada atribut. Untuk informasi selengkapnya tentang rekaman posisi, lihat artikel tentang rekaman dalam referensi bahasa C#.
Anggota non-publik dan aksesor properti
Anda dapat mengaktifkan penggunaan aksesor non-publik pada properti dengan menggunakan atribut [JsonInclude], seperti yang ditunjukkan dalam contoh berikut:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace NonPublicAccessors
{
public class Forecast
{
public DateTime Date { get; init; }
[JsonInclude]
public int TemperatureC { get; private set; }
[JsonInclude]
public string? Summary { private get; set; }
};
public class Program
{
public static void Main()
{
string json = """
{
"Date":"2020-10-23T09:51:03.8702889-07:00",
"TemperatureC":40,
"Summary":"Hot"
}
""";
Console.WriteLine($"Input JSON: {json}");
Forecast forecastDeserialized = JsonSerializer.Deserialize<Forecast>(json)!;
Console.WriteLine($"Date: {forecastDeserialized.Date}");
Console.WriteLine($"TemperatureC: {forecastDeserialized.TemperatureC}");
json = JsonSerializer.Serialize<Forecast>(forecastDeserialized);
Console.WriteLine($"Output JSON: {json}");
}
}
}
// Produces output like the following example:
//
//Input JSON: { "Date":"2020-10-23T09:51:03.8702889-07:00","TemperatureC":40,"Summary":"Hot"}
//Date: 10 / 23 / 2020 9:51:03 AM
//TemperatureC: 40
//Output JSON: { "Date":"2020-10-23T09:51:03.8702889-07:00","TemperatureC":40,"Summary":"Hot"}
Imports System.Text.Json
Imports System.Text.Json.Serialization
Namespace NonPublicAccessors
Public Class Forecast
Public Property [Date] As Date
Private _temperatureC As Integer
<JsonInclude>
Public Property TemperatureC As Integer
Get
Return _temperatureC
End Get
Private Set(Value As Integer)
_temperatureC = Value
End Set
End Property
Private _summary As String
<JsonInclude>
Public Property Summary As String
Private Get
Return _summary
End Get
Set(Value As String)
_summary = Value
End Set
End Property
End Class
Public NotInheritable Class Program
Public Shared Sub Main()
Dim json As String = "{""Date"":""2020-10-23T09:51:03.8702889-07:00"",""TemperatureC"":40,""Summary"":""Hot""}"
Console.WriteLine($"Input JSON: {json}")
Dim forecastDeserialized As Forecast = JsonSerializer.Deserialize(Of Forecast)(json)
Console.WriteLine($"Date: {forecastDeserialized.[Date]}")
Console.WriteLine($"TemperatureC: {forecastDeserialized.TemperatureC}")
json = JsonSerializer.Serialize(forecastDeserialized)
Console.WriteLine($"Output JSON: {json}")
End Sub
End Class
End Namespace
' Produces output like the following example:
'
'Input JSON: { "Date":"2020-10-23T09:51:03.8702889-07:00","TemperatureC":40,"Summary":"Hot"}
'Date: 10 / 23 / 2020 9:51:03 AM
'TemperatureC: 40
'Output JSON: { "Date":"2020-10-23T09:51:03.8702889-07:00","TemperatureC":40,"Summary":"Hot"}
Dengan menyertakan properti dengan setter privat, Anda masih dapat mendeserialisasi properti tersebut.
Di .NET 8 dan versi yang lebih baru, Anda juga dapat menggunakan atribut [JsonInclude] untuk memilih anggota non-publik ke dalam kontrak serialisasi untuk jenis tertentu.
Catatan
Dalam mode pembuatan sumber, Anda tidak dapat membuat serialisasi private
anggota atau menggunakan private
pengakses dengan membuat anotasi dengan atribut [JsonInclude ]. Dan Anda hanya dapat menserialisasikan internal
anggota atau menggunakan internal
pengakses jika mereka berada dalam rakitan yang sama dengan yang dihasilkan JsonSerializerContext.
Properti baca-saja
Di .NET 8 dan versi yang lebih baru, properti baca-saja, atau yang tidak memiliki setter baik privat atau publik, juga dapat dideserialisasi. Meskipun Anda tidak dapat mengubah instans yang dirujuk properti, jika jenis properti dapat diubah, Anda dapat memodifikasinya. Misalnya, Anda dapat menambahkan elemen ke daftar. Untuk mendeserialisasi properti baca-saja, Anda perlu mengatur perilaku penanganan pembuatan objeknya untuk mengisi alih-alih mengganti. Misalnya, Anda dapat membuat anotasi properti dengan JsonObjectCreationHandlingAttribute atribut .
class A
{
[JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)]
public List<int> Numbers1 { get; } = new List<int>() { 1, 2, 3 };
}
Untuk informasi selengkapnya, lihat Mengisi properti yang diinisialisasi.