Как использовать создание исходного кода в System.Text.Json
Создание источника в System.Text.Json доступно в .NET 6 и более поздних версиях. Создание источника состоит из двух режимов: сбора метаданных и оптимизации сериализации.
Использование значений по умолчанию для создания источника
Чтобы использовать создание источника со всеми значениями по умолчанию (оба режима, параметры по умолчанию):
Создайте разделяемый класс, производный от JsonSerializerContext.
Укажите тип для сериализации или десериализации путем применения JsonSerializableAttribute к классу контекста.
JsonSerializer Вызовите метод , который:
- JsonTypeInfo<T> Принимает экземпляр или
- JsonSerializerContext Принимает экземпляр или
- JsonSerializerOptions Принимает экземпляр , и вы задали его JsonSerializerOptions.TypeInfoResolver свойству
Default
свойство типа контекста (только .NET 7 и более поздних версий).
По умолчанию используются оба режима создания источника, если вы не указали один из них. Сведения о том, как указать используемый режим, см. в разделе Указание режима создания источника далее в этой статье.
Ниже приведен тип, используемый в следующих примерах:
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
Ниже приведен класс контекста, настроенный для создания источника для предыдущего WeatherForecast
класса:
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(WeatherForecast))]
internal partial class SourceGenerationContext : JsonSerializerContext
{
}
Типы WeatherForecast
элементов не нужно явно указывать с [JsonSerializable]
помощью атрибутов. Члены, объявленные как object
, являются исключением из этого правила. Необходимо указать тип среды выполнения для элемента, объявленного как object
. Например, предположим, что у вас есть следующий класс:
public class WeatherForecast
{
public object? Data { get; set; }
public List<object>? DataList { get; set; }
}
И вы знаете, что во время выполнения он может иметь boolean
объекты и int
:
WeatherForecast wf = new() { Data = true, DataList = new List<object> { true, 1 } };
Затем boolean
и int
должны быть объявлены как [JsonSerializable]
:
[JsonSerializable(typeof(WeatherForecast))]
[JsonSerializable(typeof(bool))]
[JsonSerializable(typeof(int))]
public partial class WeatherForecastContext : JsonSerializerContext
{
}
Чтобы указать создание источника для коллекции, используйте [JsonSerializable]
с типом коллекции. Например: [JsonSerializable(typeof(List<WeatherForecast>))]
.
JsonSerializer
методы, использующие создание источника
В следующих примерах статическое Default
свойство типа контекста предоставляет экземпляр контекстного типа с параметрами по умолчанию. Экземпляр контекста WeatherForecast
предоставляет свойство, возвращающее JsonTypeInfo<WeatherForecast>
экземпляр . Можно указать другое имя для этого свойства с помощью TypeInfoPropertyName свойства атрибута [JsonSerializable]
.
Примеры сериализации
Использование среды JsonTypeInfo<T>:
jsonString = JsonSerializer.Serialize(
weatherForecast!, SourceGenerationContext.Default.WeatherForecast);
Использование среды JsonSerializerContext:
jsonString = JsonSerializer.Serialize(
weatherForecast, typeof(WeatherForecast), SourceGenerationContext.Default);
Использование среды JsonSerializerOptions:
sourceGenOptions = new JsonSerializerOptions
{
TypeInfoResolver = SourceGenerationContext.Default
};
jsonString = JsonSerializer.Serialize(
weatherForecast, typeof(WeatherForecast), sourceGenOptions);
Примеры десериализации
Использование среды JsonTypeInfo<T>:
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(
jsonString, SourceGenerationContext.Default.WeatherForecast);
Использование среды JsonSerializerContext:
weatherForecast = JsonSerializer.Deserialize(
jsonString, typeof(WeatherForecast), SourceGenerationContext.Default)
as WeatherForecast;
Использование среды JsonSerializerOptions:
var sourceGenOptions = new JsonSerializerOptions
{
TypeInfoResolver = SourceGenerationContext.Default
};
weatherForecast = JsonSerializer.Deserialize(
jsonString, typeof(WeatherForecast), sourceGenOptions)
as WeatherForecast;
Полный пример программы
Ниже приведены приведенные выше примеры в полной программе:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace BothModesNoOptions
{
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(WeatherForecast))]
internal partial class SourceGenerationContext : JsonSerializerContext
{
}
public class Program
{
public static void Main()
{
string jsonString =
@"{
""Date"": ""2019-08-01T00:00:00"",
""TemperatureCelsius"": 25,
""Summary"": ""Hot""
}
";
WeatherForecast? weatherForecast;
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>(
jsonString, SourceGenerationContext.Default.WeatherForecast);
Console.WriteLine($"Date={weatherForecast?.Date}");
// output:
//Date=8/1/2019 12:00:00 AM
weatherForecast = JsonSerializer.Deserialize(
jsonString, typeof(WeatherForecast), SourceGenerationContext.Default)
as WeatherForecast;
Console.WriteLine($"Date={weatherForecast?.Date}");
// output:
//Date=8/1/2019 12:00:00 AM
var sourceGenOptions = new JsonSerializerOptions
{
TypeInfoResolver = SourceGenerationContext.Default
};
weatherForecast = JsonSerializer.Deserialize(
jsonString, typeof(WeatherForecast), sourceGenOptions)
as WeatherForecast;
Console.WriteLine($"Date={weatherForecast?.Date}");
// output:
//Date=8/1/2019 12:00:00 AM
jsonString = JsonSerializer.Serialize(
weatherForecast!, SourceGenerationContext.Default.WeatherForecast);
Console.WriteLine(jsonString);
// output:
//{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"}
jsonString = JsonSerializer.Serialize(
weatherForecast, typeof(WeatherForecast), SourceGenerationContext.Default);
Console.WriteLine(jsonString);
// output:
//{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"}
sourceGenOptions = new JsonSerializerOptions
{
TypeInfoResolver = SourceGenerationContext.Default
};
jsonString = JsonSerializer.Serialize(
weatherForecast, typeof(WeatherForecast), sourceGenOptions);
Console.WriteLine(jsonString);
// output:
//{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"}
}
}
}
Указание режима создания источника
Вы можете указать режим сбора метаданных или режим оптимизации сериализации для всего контекста, который может включать несколько типов. Или можно указать режим для отдельного типа. Если вы сделаете оба варианта, побеждает спецификация режима для типа.
- Для всего контекста JsonSourceGenerationOptionsAttribute.GenerationMode используйте свойство .
- Для отдельного типа используйте JsonSerializableAttribute.GenerationMode свойство .
Пример режима оптимизации сериализации
Для всего контекста:
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(WeatherForecast))] internal partial class SerializeOnlyContext : JsonSerializerContext { }
Для отдельного типа:
[JsonSerializable(typeof(WeatherForecast), GenerationMode = JsonSourceGenerationMode.Serialization)] internal partial class SerializeOnlyWeatherForecastOnlyContext : JsonSerializerContext { }
Полный пример программы
using System.Text.Json; using System.Text.Json.Serialization; namespace SerializeOnlyNoOptions { public class WeatherForecast { public DateTime Date { get; set; } public int TemperatureCelsius { get; set; } public string? Summary { get; set; } } [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(WeatherForecast))] internal partial class SerializeOnlyContext : JsonSerializerContext { } [JsonSerializable(typeof(WeatherForecast), GenerationMode = JsonSourceGenerationMode.Serialization)] internal partial class SerializeOnlyWeatherForecastOnlyContext : JsonSerializerContext { } public class Program { public static void Main() { string jsonString; WeatherForecast weatherForecast = new() { Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot" }; // Use context that selects Serialization mode only for WeatherForecast. jsonString = JsonSerializer.Serialize(weatherForecast, SerializeOnlyWeatherForecastOnlyContext.Default.WeatherForecast); Console.WriteLine(jsonString); // output: //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"} // Use a context that selects Serialization mode. jsonString = JsonSerializer.Serialize(weatherForecast, SerializeOnlyContext.Default.WeatherForecast); Console.WriteLine(jsonString); // output: //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"} } } }
Пример режима сбора метаданных
Для всего контекста:
[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(WeatherForecast))] internal partial class MetadataOnlyContext : JsonSerializerContext { }
jsonString = JsonSerializer.Serialize( weatherForecast!, MetadataOnlyContext.Default.WeatherForecast);
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>( jsonString, MetadataOnlyContext.Default.WeatherForecast);
Для отдельного типа:
[JsonSerializable(typeof(WeatherForecast), GenerationMode = JsonSourceGenerationMode.Metadata)] internal partial class MetadataOnlyWeatherForecastOnlyContext : JsonSerializerContext { }
jsonString = JsonSerializer.Serialize( weatherForecast!, MetadataOnlyWeatherForecastOnlyContext.Default.WeatherForecast);
weatherForecast = JsonSerializer.Deserialize<WeatherForecast>( jsonString, MetadataOnlyWeatherForecastOnlyContext.Default.WeatherForecast);
Полный пример программы
using System.Text.Json; using System.Text.Json.Serialization; namespace MetadataOnlyNoOptions { public class WeatherForecast { public DateTime Date { get; set; } public int TemperatureCelsius { get; set; } public string? Summary { get; set; } } [JsonSerializable(typeof(WeatherForecast), GenerationMode = JsonSourceGenerationMode.Metadata)] internal partial class MetadataOnlyWeatherForecastOnlyContext : JsonSerializerContext { } [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(WeatherForecast))] internal partial class MetadataOnlyContext : JsonSerializerContext { } public class Program { public static void Main() { string jsonString = @"{ ""Date"": ""2019-08-01T00:00:00"", ""TemperatureCelsius"": 25, ""Summary"": ""Hot"" } "; WeatherForecast? weatherForecast; // Deserialize with context that selects metadata mode only for WeatherForecast only. weatherForecast = JsonSerializer.Deserialize<WeatherForecast>( jsonString, MetadataOnlyWeatherForecastOnlyContext.Default.WeatherForecast); Console.WriteLine($"Date={weatherForecast?.Date}"); // output: //Date=8/1/2019 12:00:00 AM // Serialize with context that selects metadata mode only for WeatherForecast only. jsonString = JsonSerializer.Serialize( weatherForecast!, MetadataOnlyWeatherForecastOnlyContext.Default.WeatherForecast); Console.WriteLine(jsonString); // output: //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":25,"Summary":"Hot"} // Deserialize with context that selects metadata mode only. weatherForecast = JsonSerializer.Deserialize<WeatherForecast>( jsonString, MetadataOnlyContext.Default.WeatherForecast); Console.WriteLine($"Date={weatherForecast?.Date}"); // output: //Date=8/1/2019 12:00:00 AM // Serialize with context that selects metadata mode only. jsonString = JsonSerializer.Serialize( weatherForecast!, MetadataOnlyContext.Default.WeatherForecast); Console.WriteLine(jsonString); // output: //{"Date":"2019-08-01T00:00:00","TemperatureCelsius":0,"Summary":"Hot"} } } }
Указание параметров для режима оптимизации сериализации
Используйте для JsonSourceGenerationOptionsAttribute указания параметров, поддерживаемых режимом оптимизации сериализации. Эти параметры можно использовать без отката кода JsonSerializer
. Например, WriteIndented
поддерживаются и CamelCase
:
[JsonSourceGenerationOptions(
WriteIndented = true,
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(WeatherForecast))]
internal partial class SerializationModeOptionsContext : JsonSerializerContext
{
}
При использовании JsonSourceGenerationOptionsAttribute
для указания параметров сериализации вызовите один из следующих методов сериализации:
Метод
JsonSerializer.Serialize
, принимаюющийTypeInfo<TValue>
. Передайте его свойствуDefault.<TypeName>
класса контекста:jsonString = JsonSerializer.Serialize( weatherForecast, SerializationModeOptionsContext.Default.WeatherForecast);
Метод
JsonSerializer.Serialize
, который принимает контекст. Передайте емуDefault
статическое свойство контекстного класса.jsonString = JsonSerializer.Serialize( weatherForecast, typeof(WeatherForecast), SerializationModeOptionsContext.Default);
При вызове метода, который позволяет передать собственный Utf8JsonWriter
экземпляр , параметр модуля записи Indented учитывается вместо JsonSourceGenerationOptionsAttribute.WriteIndented
параметра .
Если вы создаете и используете экземпляр контекста путем вызова конструктора, принимающего JsonSerializerOptions
экземпляр, указанный экземпляр будет использоваться вместо параметров, заданных параметром JsonSourceGenerationOptionsAttribute
.
Ниже приведены приведенные выше примеры в полной программе:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SerializeOnlyWithOptions
{
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
[JsonSourceGenerationOptions(
WriteIndented = true,
PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase,
GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(WeatherForecast))]
internal partial class SerializationModeOptionsContext : JsonSerializerContext
{
}
public class Program
{
public static void Main()
{
string jsonString;
WeatherForecast weatherForecast = new()
{ Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot" };
// Serialize using TypeInfo<TValue> provided by the context
// and options specified by [JsonSourceGenerationOptions].
jsonString = JsonSerializer.Serialize(
weatherForecast, SerializationModeOptionsContext.Default.WeatherForecast);
Console.WriteLine(jsonString);
// output:
//{
// "date": "2019-08-01T00:00:00",
// "temperatureCelsius": 0,
// "summary": "Hot"
//}
// Serialize using Default context
// and options specified by [JsonSourceGenerationOptions].
jsonString = JsonSerializer.Serialize(
weatherForecast, typeof(WeatherForecast), SerializationModeOptionsContext.Default);
Console.WriteLine(jsonString);
// output:
//{
// "date": "2019-08-01T00:00:00",
// "temperatureCelsius": 0,
// "summary": "Hot"
//}
}
}
}
Указание параметров с помощью JsonSerializerOptions
Некоторые параметры JsonSerializerOptions не поддерживаются режимом оптимизации сериализации. Такие параметры приводят к откату к коду, не созданному JsonSerializer
исходным кодом. Дополнительные сведения см. в разделе Оптимизация сериализации.
Указание параметров с помощью JsonSerializerOptions:
- Создание экземпляра
JsonSerializerOptions
. - Создайте экземпляр класса, производного от JsonSerializerContext, и передайте
JsonSerializerOptions
экземпляр конструктору. - Вызовите методы сериализации или десериализации , которые принимают экземпляр контекста
JsonSerializer
илиTypeInfo<TValue>
.
Ниже приведен пример класса контекста, за которым следует пример кода сериализации и десериализации:
[JsonSerializable(typeof(WeatherForecast))]
internal partial class OptionsExampleContext : JsonSerializerContext
{
}
jsonString = JsonSerializer.Serialize(
weatherForecast,
typeof(WeatherForecast),
new OptionsExampleContext(
new JsonSerializerOptions(JsonSerializerDefaults.Web)));
weatherForecast = JsonSerializer.Deserialize(
jsonString,
typeof(WeatherForecast),
new OptionsExampleContext(
new JsonSerializerOptions(JsonSerializerDefaults.Web)))
as WeatherForecast;
Ниже приведены приведенные выше примеры в полной программе:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace JsonSerializerOptionsExample
{
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
[JsonSerializable(typeof(WeatherForecast))]
internal partial class OptionsExampleContext : JsonSerializerContext
{
}
public class Program
{
public static void Main()
{
string jsonString =
@"{
""date"": ""2019-08-01T00:00:00"",
""temperatureCelsius"": 25,
""summary"": ""Hot""
}
";
WeatherForecast? weatherForecast;
weatherForecast = JsonSerializer.Deserialize(
jsonString,
typeof(WeatherForecast),
new OptionsExampleContext(
new JsonSerializerOptions(JsonSerializerDefaults.Web)))
as WeatherForecast;
Console.WriteLine($"Date={weatherForecast?.Date}");
// output:
//Date=8/1/2019 12:00:00 AM
jsonString = JsonSerializer.Serialize(
weatherForecast,
typeof(WeatherForecast),
new OptionsExampleContext(
new JsonSerializerOptions(JsonSerializerDefaults.Web)));
Console.WriteLine(jsonString);
// output:
//{ "date":"2019-08-01T00:00:00","temperatureCelsius":25,"summary":"Hot"}
}
}
}
Поддержка создания источников в ASP.NET Core
В приложениях Blazor:
Используйте перегрузки HttpClientJsonExtensions.GetFromJsonAsync методов расширения и HttpClientJsonExtensions.PostAsJsonAsync , которые принимают контекст создания источника или
TypeInfo<TValue>
.В приложениях Razor Pages, MVC, SignalR и веб-API:
AddContext Используйте метод JsonSerializerOptions, как показано в следующем примере:
[JsonSerializable(typeof(WeatherForecast[]))] internal partial class MyJsonContext : JsonSerializerContext { }
services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.AddContext<MyJsonContext>());