JsonSerializerOptions
Provides options to be used with JsonSerializer.
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.Encodings.Web;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Converters;
namespace System.Text.Json
{
[System.Runtime.CompilerServices.NullableContext(2)]
[System.Runtime.CompilerServices.Nullable(0)]
public sealed class JsonSerializerOptions
{
private static readonly Dictionary<Type, JsonConverter> s_defaultSimpleConverters = GetDefaultSimpleConverters();
private static readonly List<JsonConverter> s_defaultFactoryConverters = GetDefaultConverters();
private readonly ConcurrentDictionary<Type, JsonConverter> _converters = new ConcurrentDictionary<Type, JsonConverter>();
private const int NumberOfSimpleConverters = 21;
internal const int BufferSizeDefault = 16384;
internal static readonly JsonSerializerOptions s_defaultOptions = new JsonSerializerOptions();
private readonly ConcurrentDictionary<Type, JsonClassInfo> _classes = new ConcurrentDictionary<Type, JsonClassInfo>();
private MemberAccessor _memberAccessorStrategy;
private JsonNamingPolicy _dictionaryKeyPolicy;
private JsonNamingPolicy _jsonPropertyNamingPolicy;
private JsonCommentHandling _readCommentHandling;
private ReferenceHandling _referenceHandling = ReferenceHandling.Default;
private JavaScriptEncoder _encoder;
private int _defaultBufferSize = 16384;
private int _maxDepth;
private bool _allowTrailingCommas;
private bool _haveTypesBeenCreated;
private bool _ignoreNullValues;
private bool _ignoreReadOnlyProperties;
private bool _propertyNameCaseInsensitive;
private bool _writeIndented;
[System.Runtime.CompilerServices.Nullable(1)]
public IList<JsonConverter> Converters {
[System.Runtime.CompilerServices.NullableContext(1)]
get;
}
[System.Runtime.CompilerServices.Nullable(1)]
private static IEnumerable<JsonConverter> DefaultSimpleConverters {
get {
yield return (JsonConverter)new BooleanConverter();
yield return (JsonConverter)new ByteConverter();
yield return (JsonConverter)new ByteArrayConverter();
yield return (JsonConverter)new CharConverter();
yield return (JsonConverter)new DateTimeConverter();
yield return (JsonConverter)new DateTimeOffsetConverter();
yield return (JsonConverter)new DoubleConverter();
yield return (JsonConverter)new DecimalConverter();
yield return (JsonConverter)new GuidConverter();
yield return (JsonConverter)new Int16Converter();
yield return (JsonConverter)new Int32Converter();
yield return (JsonConverter)new Int64Converter();
yield return (JsonConverter)new JsonElementConverter();
yield return (JsonConverter)new ObjectConverter();
yield return (JsonConverter)new SByteConverter();
yield return (JsonConverter)new SingleConverter();
yield return (JsonConverter)new StringConverter();
yield return (JsonConverter)new UInt16Converter();
yield return (JsonConverter)new UInt32Converter();
yield return (JsonConverter)new UInt64Converter();
yield return (JsonConverter)new UriConverter();
}
}
public bool AllowTrailingCommas {
get {
return _allowTrailingCommas;
}
set {
VerifyMutable();
_allowTrailingCommas = value;
}
}
public int DefaultBufferSize {
get {
return _defaultBufferSize;
}
set {
VerifyMutable();
if (value < 1)
throw new ArgumentException(System.SR.SerializationInvalidBufferSize);
_defaultBufferSize = value;
}
}
public JavaScriptEncoder Encoder {
get {
return _encoder;
}
set {
VerifyMutable();
_encoder = value;
}
}
public JsonNamingPolicy DictionaryKeyPolicy {
get {
return _dictionaryKeyPolicy;
}
set {
VerifyMutable();
_dictionaryKeyPolicy = value;
}
}
public bool IgnoreNullValues {
get {
return _ignoreNullValues;
}
set {
VerifyMutable();
_ignoreNullValues = value;
}
}
public bool IgnoreReadOnlyProperties {
get {
return _ignoreReadOnlyProperties;
}
set {
VerifyMutable();
_ignoreReadOnlyProperties = value;
}
}
public int MaxDepth {
get {
return _maxDepth;
}
set {
VerifyMutable();
if (value < 0)
throw ThrowHelper.GetArgumentOutOfRangeException_MaxDepthMustBePositive("value");
_maxDepth = value;
EffectiveMaxDepth = ((value == 0) ? 64 : value);
}
}
internal int EffectiveMaxDepth { get; set; } = 64;
public JsonNamingPolicy PropertyNamingPolicy {
get {
return _jsonPropertyNamingPolicy;
}
set {
VerifyMutable();
_jsonPropertyNamingPolicy = value;
}
}
public bool PropertyNameCaseInsensitive {
get {
return _propertyNameCaseInsensitive;
}
set {
VerifyMutable();
_propertyNameCaseInsensitive = value;
}
}
public JsonCommentHandling ReadCommentHandling {
get {
return _readCommentHandling;
}
set {
VerifyMutable();
if ((int)value > 1)
throw new ArgumentOutOfRangeException("value", System.SR.JsonSerializerDoesNotSupportComments);
_readCommentHandling = value;
}
}
public bool WriteIndented {
get {
return _writeIndented;
}
set {
VerifyMutable();
_writeIndented = value;
}
}
[System.Runtime.CompilerServices.Nullable(1)]
public ReferenceHandling ReferenceHandling {
[System.Runtime.CompilerServices.NullableContext(1)]
get {
return _referenceHandling;
}
[System.Runtime.CompilerServices.NullableContext(1)]
set {
VerifyMutable();
if (value == null)
throw new ArgumentNullException("value");
_referenceHandling = value;
}
}
[System.Runtime.CompilerServices.Nullable(1)]
internal MemberAccessor MemberAccessorStrategy {
get {
if (_memberAccessorStrategy == null)
_memberAccessorStrategy = new ReflectionMemberAccessor();
return _memberAccessorStrategy;
}
}
private static Dictionary<Type, JsonConverter> GetDefaultSimpleConverters()
{
Dictionary<Type, JsonConverter> dictionary = new Dictionary<Type, JsonConverter>(21);
foreach (JsonConverter defaultSimpleConverter in DefaultSimpleConverters) {
dictionary.Add(defaultSimpleConverter.TypeToConvert, defaultSimpleConverter);
}
return dictionary;
}
private static List<JsonConverter> GetDefaultConverters()
{
List<JsonConverter> list = new List<JsonConverter>(5);
list.Add(new NullableConverterFactory());
list.Add(new EnumConverterFactory());
list.Add(new KeyValuePairConverterFactory());
list.Add(new JsonIEnumerableConverterFactory());
list.Add(new ObjectConverterFactory());
return list;
}
internal JsonConverter DetermineConverter(Type parentClassType, Type runtimePropertyType, PropertyInfo propertyInfo)
{
JsonConverter jsonConverter = null;
if (propertyInfo != (PropertyInfo)null) {
JsonConverterAttribute jsonConverterAttribute = (JsonConverterAttribute)GetAttributeThatCanHaveMultiple(parentClassType, typeof(JsonConverterAttribute), propertyInfo);
if (jsonConverterAttribute != null)
jsonConverter = GetConverterFromAttribute(jsonConverterAttribute, runtimePropertyType, parentClassType, propertyInfo);
}
if (jsonConverter == null)
jsonConverter = GetConverter(runtimePropertyType);
JsonConverterFactory jsonConverterFactory = jsonConverter as JsonConverterFactory;
if (jsonConverterFactory != null)
jsonConverter = jsonConverterFactory.GetConverterInternal(runtimePropertyType, this);
return jsonConverter;
}
[System.Runtime.CompilerServices.NullableContext(1)]
[return: System.Runtime.CompilerServices.Nullable(2)]
public JsonConverter GetConverter(Type typeToConvert)
{
if (_converters.TryGetValue(typeToConvert, out JsonConverter value))
return value;
foreach (JsonConverter converter in Converters) {
if (converter.CanConvert(typeToConvert)) {
value = converter;
break;
}
}
if (value == null) {
JsonConverterAttribute jsonConverterAttribute = (JsonConverterAttribute)GetAttributeThatCanHaveMultiple(typeToConvert, typeof(JsonConverterAttribute));
if (jsonConverterAttribute != null)
value = GetConverterFromAttribute(jsonConverterAttribute, typeToConvert, typeToConvert, null);
}
if (value == null) {
if (s_defaultSimpleConverters.TryGetValue(typeToConvert, out JsonConverter value2))
value = value2;
else {
foreach (JsonConverter s_defaultFactoryConverter in s_defaultFactoryConverters) {
if (s_defaultFactoryConverter.CanConvert(typeToConvert)) {
value = s_defaultFactoryConverter;
break;
}
}
}
}
JsonConverterFactory jsonConverterFactory = value as JsonConverterFactory;
if (jsonConverterFactory != null)
value = jsonConverterFactory.GetConverterInternal(typeToConvert, this);
if (value != null) {
Type typeToConvert2 = value.TypeToConvert;
if (!typeToConvert2.IsAssignableFrom(typeToConvert) && !typeToConvert.IsAssignableFrom(typeToConvert2))
ThrowHelper.ThrowInvalidOperationException_SerializationConverterNotCompatible(value.GetType(), typeToConvert);
}
if (_haveTypesBeenCreated)
_converters.TryAdd(typeToConvert, value);
return value;
}
private JsonConverter GetConverterFromAttribute(JsonConverterAttribute converterAttribute, Type typeToConvert, Type classTypeAttributeIsOn, PropertyInfo propertyInfo)
{
Type converterType = converterAttribute.ConverterType;
JsonConverter jsonConverter;
if (converterType == (Type)null) {
jsonConverter = converterAttribute.CreateConverter(typeToConvert);
if (jsonConverter == null)
ThrowHelper.ThrowInvalidOperationException_SerializationConverterOnAttributeNotCompatible(classTypeAttributeIsOn, propertyInfo, typeToConvert);
} else {
ConstructorInfo constructor = converterType.GetConstructor(Type.EmptyTypes);
if (!typeof(JsonConverter).IsAssignableFrom(converterType) || constructor == (ConstructorInfo)null || !constructor.IsPublic)
ThrowHelper.ThrowInvalidOperationException_SerializationConverterOnAttributeInvalid(classTypeAttributeIsOn, propertyInfo);
jsonConverter = (JsonConverter)Activator.CreateInstance(converterType);
}
if (!jsonConverter.CanConvert(typeToConvert)) {
Type underlyingType = Nullable.GetUnderlyingType(typeToConvert);
if (underlyingType != (Type)null && jsonConverter.CanConvert(underlyingType))
return NullableConverterFactory.CreateValueConverter(underlyingType, jsonConverter);
ThrowHelper.ThrowInvalidOperationException_SerializationConverterOnAttributeNotCompatible(classTypeAttributeIsOn, propertyInfo, typeToConvert);
}
return jsonConverter;
}
private static Attribute GetAttributeThatCanHaveMultiple(Type classType, Type attributeType, PropertyInfo propertyInfo)
{
object[] customAttributes = propertyInfo.GetCustomAttributes(attributeType, false);
return GetAttributeThatCanHaveMultiple(attributeType, classType, propertyInfo, customAttributes);
}
private static Attribute GetAttributeThatCanHaveMultiple(Type classType, Type attributeType)
{
object[] customAttributes = classType.GetCustomAttributes(attributeType, false);
return GetAttributeThatCanHaveMultiple(attributeType, classType, null, customAttributes);
}
private static Attribute GetAttributeThatCanHaveMultiple(Type attributeType, Type classType, PropertyInfo propertyInfo, object[] attributes)
{
if (attributes.Length == 0)
return null;
if (attributes.Length == 1)
return (Attribute)attributes[0];
ThrowHelper.ThrowInvalidOperationException_SerializationDuplicateAttribute(attributeType, classType, propertyInfo);
return null;
}
public JsonSerializerOptions()
{
Converters = new ConverterList(this);
}
internal JsonClassInfo GetOrAddClass(Type classType)
{
_haveTypesBeenCreated = true;
if (_classes.TryGetValue(classType, out JsonClassInfo value))
return value;
value = _classes.GetOrAdd(classType, new JsonClassInfo(classType, this));
return value;
}
internal JsonReaderOptions GetReaderOptions()
{
JsonReaderOptions result = default(JsonReaderOptions);
result.AllowTrailingCommas = AllowTrailingCommas;
result.CommentHandling = ReadCommentHandling;
result.MaxDepth = MaxDepth;
return result;
}
internal JsonWriterOptions GetWriterOptions()
{
JsonWriterOptions result = default(JsonWriterOptions);
result.Encoder = Encoder;
result.Indented = WriteIndented;
result.SkipValidation = true;
return result;
}
internal void VerifyMutable()
{
if (_haveTypesBeenCreated)
ThrowHelper.ThrowInvalidOperationException_SerializerOptionsImmutable();
}
}
}