<PackageReference Include="System.Text.Json" Version="10.0.0-preview.2.25163.2" />

JsonPropertyInfo

public abstract class JsonPropertyInfo
Provides JSON serialization-related metadata about a property or field.
using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; namespace System.Text.Json.Serialization.Metadata { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] [DebuggerDisplay("{DebuggerDisplay,nq}")] public abstract class JsonPropertyInfo { internal static readonly JsonPropertyInfo s_missingProperty = GetPropertyPlaceholder(); private protected JsonConverter _effectiveConverter; private JsonConverter _customConverter; private protected Func<object, object> _untypedGet; private protected Action<object, object> _untypedSet; private bool _isUserSpecifiedSetter; private protected Func<object, object, bool> _shouldSerialize; private bool _isUserSpecifiedShouldSerialize; private JsonIgnoreCondition? _ignoreCondition; internal Func<ICustomAttributeProvider> AttributeProviderFactory; private ICustomAttributeProvider _attributeProvider; private JsonObjectCreationHandling? _objectCreationHandling; private bool _isGetNullable; private protected bool _isSetNullable; private bool _isExtensionDataProperty; private protected bool _isRequired; private string _name; private int _order; private JsonTypeInfo _jsonTypeInfo; private JsonNumberHandling? _numberHandling; private int _index; [System.Runtime.CompilerServices.Nullable(2)] internal JsonTypeInfo DeclaringTypeInfo { get; set; } internal JsonConverter EffectiveConverter => _effectiveConverter; [System.Runtime.CompilerServices.Nullable(2)] public JsonConverter CustomConverter { [System.Runtime.CompilerServices.NullableContext(2)] get { return _customConverter; } [System.Runtime.CompilerServices.NullableContext(2)] set { VerifyMutable(); _customConverter = value; } } [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1, 2 })] public Func<object, object> Get { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1, 2 })] get { return _untypedGet; } [param: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1, 2 })] set { VerifyMutable(); SetGetter(value); } } [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1, 2 })] public Action<object, object> Set { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1, 2 })] get { return _untypedSet; } [param: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1, 2 })] set { VerifyMutable(); SetSetter(value); _isUserSpecifiedSetter = true; } } [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1, 2 })] public Func<object, object, bool> ShouldSerialize { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1, 2 })] get { return _shouldSerialize; } [param: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1, 2 })] set { VerifyMutable(); SetShouldSerialize(value); _isUserSpecifiedShouldSerialize = true; IgnoreDefaultValuesOnWrite = false; } } internal JsonIgnoreCondition? IgnoreCondition { get { return _ignoreCondition; } set { ConfigureIgnoreCondition(value); _ignoreCondition = value; } } [System.Runtime.CompilerServices.Nullable(2)] public ICustomAttributeProvider AttributeProvider { [System.Runtime.CompilerServices.NullableContext(2)] get { Func<ICustomAttributeProvider> func = Volatile.Read(ref AttributeProviderFactory); ICustomAttributeProvider customAttributeProvider = _attributeProvider; if (customAttributeProvider == null && func != null) { customAttributeProvider = (_attributeProvider = func()); Volatile.Write(ref AttributeProviderFactory, null); } return customAttributeProvider; } [System.Runtime.CompilerServices.NullableContext(2)] set { VerifyMutable(); _attributeProvider = value; Volatile.Write(ref AttributeProviderFactory, null); } } public JsonObjectCreationHandling? ObjectCreationHandling { get { return _objectCreationHandling; } set { VerifyMutable(); if (value.HasValue && !JsonSerializer.IsValidCreationHandlingValue(value.Value)) throw new ArgumentOutOfRangeException("value"); _objectCreationHandling = value; } } internal JsonObjectCreationHandling EffectiveObjectCreationHandling { get; set; } [System.Runtime.CompilerServices.Nullable(2)] internal string MemberName { get; set; } internal MemberTypes MemberType { get; set; } internal bool IsVirtual { get; set; } public bool IsGetNullable { get { return _isGetNullable; } set { VerifyMutable(); if (value && !PropertyTypeCanBeNull) ThrowHelper.ThrowInvalidOperationException_PropertyTypeNotNullable(this); _isGetNullable = value; } } public bool IsSetNullable { get { return _isSetNullable; } set { VerifyMutable(); if (value && !PropertyTypeCanBeNull) ThrowHelper.ThrowInvalidOperationException_PropertyTypeNotNullable(this); _isSetNullable = value; } } public bool IsExtensionData { get { return _isExtensionDataProperty; } set { VerifyMutable(); if (value && !JsonTypeInfo.IsValidExtensionDataProperty(PropertyType)) ThrowHelper.ThrowInvalidOperationException_SerializationDataExtensionPropertyInvalid(this); _isExtensionDataProperty = value; } } public bool IsRequired { get { return _isRequired; } set { VerifyMutable(); _isRequired = value; } } [System.Runtime.CompilerServices.Nullable(2)] public JsonParameterInfo AssociatedParameter { [System.Runtime.CompilerServices.NullableContext(2)] get; internal set; } public Type DeclaringType { get; } public Type PropertyType { get; } internal bool IsConfigured { get; set; } internal bool HasGetter => _untypedGet != null; internal bool HasSetter => _untypedSet != null; internal bool IgnoreNullTokensOnRead { get; set; } internal bool IgnoreDefaultValuesOnWrite { get; set; } internal bool IgnoreReadOnlyMember { get { switch (MemberType) { case MemberTypes.Property: return Options.IgnoreReadOnlyProperties; case MemberTypes.Field: return Options.IgnoreReadOnlyFields; default: return false; } } } internal bool IsForTypeInfo { get; set; } public string Name { get { return _name; } set { VerifyMutable(); if (value == null) ThrowHelper.ThrowArgumentNullException("value"); _name = value; } } internal byte[] NameAsUtf8Bytes { get; set; } internal byte[] EscapedNameSection { get; set; } public JsonSerializerOptions Options { get; } public int Order { get { return _order; } set { VerifyMutable(); _order = value; } } internal JsonTypeInfo JsonTypeInfo { get { JsonTypeInfo jsonTypeInfo = _jsonTypeInfo; jsonTypeInfo.EnsureConfigured(); return jsonTypeInfo; } set { _jsonTypeInfo = value; } } internal bool IsPropertyTypeInfoConfigured => _jsonTypeInfo?.IsConfigured ?? false; internal bool IsIgnored { get { JsonIgnoreCondition? ignoreCondition = _ignoreCondition; if (ignoreCondition.HasValue && ignoreCondition.GetValueOrDefault() == JsonIgnoreCondition.Always && Get == null) return Set == null; return false; } } internal bool CanSerialize { get; set; } internal bool CanDeserialize { get; set; } internal bool CanDeserializeOrPopulate { get; set; } internal bool SrcGen_HasJsonInclude { get; set; } internal bool SrcGen_IsPublic { get; set; } public JsonNumberHandling? NumberHandling { get { return _numberHandling; } set { VerifyMutable(); _numberHandling = value; } } internal JsonNumberHandling? EffectiveNumberHandling { get; set; } internal abstract bool PropertyTypeCanBeNull { get; } [System.Runtime.CompilerServices.Nullable(2)] internal abstract object DefaultValue { get; } [DebuggerBrowsable(DebuggerBrowsableState.Never)] internal int RequiredPropertyIndex { get { return _index; } set { _index = value; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay { get { return $"""{Name}""{PropertyType}"; } } private protected abstract void SetGetter(Delegate getter); private protected abstract void SetSetter(Delegate setter); private protected abstract void SetShouldSerialize(Delegate predicate); private protected abstract void ConfigureIgnoreCondition(JsonIgnoreCondition? ignoreCondition); internal JsonPropertyInfo(Type declaringType, Type propertyType, JsonTypeInfo declaringTypeInfo, JsonSerializerOptions options) { DeclaringType = declaringType; PropertyType = propertyType; DeclaringTypeInfo = declaringTypeInfo; Options = options; _isGetNullable = (_isSetNullable = PropertyTypeCanBeNull); } internal static JsonPropertyInfo GetPropertyPlaceholder() { return new JsonPropertyInfo<object>(typeof(object), null, null) { Name = string.Empty }; } private protected void VerifyMutable() { DeclaringTypeInfo?.VerifyMutable(); } internal void Configure() { if (IsIgnored) { CanSerialize = false; CanDeserialize = false; } else { if (_jsonTypeInfo == null) _jsonTypeInfo = Options.GetTypeInfoInternal(PropertyType, true, true, false, false); _jsonTypeInfo.EnsureConfigured(); DetermineEffectiveConverter(_jsonTypeInfo); DetermineNumberHandlingForProperty(); DetermineEffectiveObjectCreationHandlingForProperty(); DetermineSerializationCapabilities(); DetermineIgnoreCondition(); } if (IsForTypeInfo) DetermineNumberHandlingForTypeInfo(); else ValidateAndCachePropertyName(); if (IsRequired) { if (!CanDeserialize) { bool? nullable = AssociatedParameter?.IsRequiredParameter; if (!nullable.HasValue || !nullable.GetValueOrDefault() || !Options.RespectRequiredConstructorParameters) ThrowHelper.ThrowInvalidOperationException_JsonPropertyRequiredAndNotDeserializable(this); } if (IsExtensionData) ThrowHelper.ThrowInvalidOperationException_JsonPropertyRequiredAndExtensionData(this); } IsConfigured = true; } private protected abstract void DetermineEffectiveConverter(JsonTypeInfo jsonTypeInfo); [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.")] internal abstract void DetermineReflectionPropertyAccessors(MemberInfo memberInfo, bool useNonPublicAccessors); private void ValidateAndCachePropertyName() { int num; if (Options.ReferenceHandlingStrategy == JsonKnownReferenceHandler.Preserve) { if (this != null) { Type declaringType = DeclaringType; if ((object)declaringType != null && !declaringType.IsValueType && !IsIgnored) { num = ((!IsExtensionData) ? 1 : 0); goto IL_003c; } } num = 0; } else num = 0; goto IL_003c; IL_003c: bool flag = (byte)num != 0; if (flag) { string name = Name; bool flag2 = (name == "$id" || name == "$ref") ? true : false; flag = flag2; } if (flag) ThrowHelper.ThrowInvalidOperationException_PropertyConflictsWithMetadataPropertyName(DeclaringType, Name); NameAsUtf8Bytes = Encoding.UTF8.GetBytes(Name); EscapedNameSection = JsonHelpers.GetEscapedPropertyNameSection(NameAsUtf8Bytes, Options.Encoder); } private void DetermineIgnoreCondition() { if (!_ignoreCondition.HasValue) { if (Options.IgnoreNullValues) { if (PropertyTypeCanBeNull) { IgnoreNullTokensOnRead = (!_isUserSpecifiedSetter && !IsRequired); IgnoreDefaultValuesOnWrite = (ShouldSerialize == null); } } else if (Options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingNull) { if (PropertyTypeCanBeNull) IgnoreDefaultValuesOnWrite = (ShouldSerialize == null); } else if (Options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingDefault) { IgnoreDefaultValuesOnWrite = (ShouldSerialize == null); } } } private void DetermineSerializationCapabilities() { CanSerialize = HasGetter; CanDeserialize = HasSetter; if (MemberType == (MemberTypes)0 || _ignoreCondition.HasValue) CanDeserializeOrPopulate = (CanDeserialize || EffectiveObjectCreationHandling == JsonObjectCreationHandling.Populate); else { if ((EffectiveConverter.ConverterStrategy & (ConverterStrategy)24) != 0) { if (Get == null && Set != null && !_isUserSpecifiedSetter) CanDeserialize = false; } else if (Get != null && Set == null && IgnoreReadOnlyMember && !_isUserSpecifiedShouldSerialize) { CanSerialize = false; } CanDeserializeOrPopulate = (CanDeserialize || EffectiveObjectCreationHandling == JsonObjectCreationHandling.Populate); } } private void DetermineNumberHandlingForTypeInfo() { JsonNumberHandling? numberHandling = DeclaringTypeInfo.NumberHandling; if (numberHandling.HasValue) { JsonNumberHandling? nullable = numberHandling; JsonNumberHandling jsonNumberHandling = JsonNumberHandling.Strict; if (!((nullable.GetValueOrDefault() == jsonNumberHandling) & nullable.HasValue) && !EffectiveConverter.IsInternalConverter) ThrowHelper.ThrowInvalidOperationException_NumberHandlingOnPropertyInvalid(this); } if (NumberHandingIsApplicable()) { EffectiveNumberHandling = numberHandling; if (!EffectiveNumberHandling.HasValue && Options.NumberHandling != 0) EffectiveNumberHandling = Options.NumberHandling; } } private void DetermineNumberHandlingForProperty() { if (NumberHandingIsApplicable()) { JsonNumberHandling? effectiveNumberHandling = NumberHandling ?? DeclaringTypeInfo.NumberHandling ?? _jsonTypeInfo.NumberHandling; if (!effectiveNumberHandling.HasValue && Options.NumberHandling != 0) effectiveNumberHandling = Options.NumberHandling; EffectiveNumberHandling = effectiveNumberHandling; } else if (NumberHandling.HasValue) { JsonNumberHandling? numberHandling = NumberHandling; JsonNumberHandling jsonNumberHandling = JsonNumberHandling.Strict; if (!((numberHandling.GetValueOrDefault() == jsonNumberHandling) & numberHandling.HasValue)) ThrowHelper.ThrowInvalidOperationException_NumberHandlingOnPropertyInvalid(this); } } private void DetermineEffectiveObjectCreationHandlingForProperty() { JsonObjectCreationHandling jsonObjectCreationHandling = JsonObjectCreationHandling.Replace; if (!ObjectCreationHandling.HasValue) jsonObjectCreationHandling = (((DeclaringTypeInfo.PreferredPropertyObjectCreationHandling ?? ((!DeclaringTypeInfo.DetermineUsesParameterizedConstructor()) ? Options.PreferredObjectCreationHandling : JsonObjectCreationHandling.Replace)) == JsonObjectCreationHandling.Populate && EffectiveConverter.CanPopulate && Get != null && (!PropertyType.IsValueType || Set != null) && !DeclaringTypeInfo.SupportsPolymorphicDeserialization && (Set != null || !IgnoreReadOnlyMember)) ? JsonObjectCreationHandling.Populate : JsonObjectCreationHandling.Replace); else if (ObjectCreationHandling.GetValueOrDefault() == JsonObjectCreationHandling.Populate) { if (!EffectiveConverter.CanPopulate) ThrowHelper.ThrowInvalidOperationException_ObjectCreationHandlingPopulateNotSupportedByConverter(this); if (Get == null) ThrowHelper.ThrowInvalidOperationException_ObjectCreationHandlingPropertyMustHaveAGetter(this); if (PropertyType.IsValueType && Set == null) ThrowHelper.ThrowInvalidOperationException_ObjectCreationHandlingPropertyValueTypeMustHaveASetter(this); if (JsonTypeInfo.SupportsPolymorphicDeserialization) ThrowHelper.ThrowInvalidOperationException_ObjectCreationHandlingPropertyCannotAllowPolymorphicDeserialization(this); if (Set == null && IgnoreReadOnlyMember) ThrowHelper.ThrowInvalidOperationException_ObjectCreationHandlingPropertyCannotAllowReadOnlyMember(this); jsonObjectCreationHandling = JsonObjectCreationHandling.Populate; } if (jsonObjectCreationHandling == JsonObjectCreationHandling.Populate) { if (DeclaringTypeInfo.DetermineUsesParameterizedConstructor()) ThrowHelper.ThrowNotSupportedException_ObjectCreationHandlingPropertyDoesNotSupportParameterizedConstructors(); if (Options.ReferenceHandlingStrategy != 0) ThrowHelper.ThrowInvalidOperationException_ObjectCreationHandlingPropertyCannotAllowReferenceHandling(); } EffectiveObjectCreationHandling = jsonObjectCreationHandling; } private bool NumberHandingIsApplicable() { if (EffectiveConverter.IsInternalConverterForNumberType) return true; Type type = (EffectiveConverter.IsInternalConverter && ((ConverterStrategy)24 & EffectiveConverter.ConverterStrategy) != 0) ? EffectiveConverter.ElementType : PropertyType; type = (Nullable.GetUnderlyingType(type) ?? type); if (!(type == typeof(byte)) && !(type == typeof(decimal)) && !(type == typeof(double)) && !(type == typeof(short)) && !(type == typeof(int)) && !(type == typeof(long)) && !(type == typeof(sbyte)) && !(type == typeof(float)) && !(type == typeof(ushort)) && !(type == typeof(uint)) && !(type == typeof(ulong))) return type == JsonTypeInfo.ObjectType; return true; } internal abstract void AddJsonParameterInfo(JsonParameterInfoValues parameterInfoValues); internal abstract bool GetMemberAndWriteJson(object obj, ref WriteStack state, Utf8JsonWriter writer); internal abstract bool GetMemberAndWriteJsonExtensionData(object obj, ref WriteStack state, Utf8JsonWriter writer); internal abstract object GetValueAsObject(object obj); internal bool ReadJsonAndAddExtensionProperty(object obj, [System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, ref Utf8JsonReader reader) { object valueAsObject = GetValueAsObject(obj); IDictionary<string, object> dictionary = valueAsObject as IDictionary<string, object>; if (dictionary != null) { if (reader.TokenType == JsonTokenType.Null) dictionary[state.Current.JsonPropertyNameAsString] = null; else { object value = <ReadJsonAndAddExtensionProperty>g__GetDictionaryValueConverter|143_0<object>().Read(ref reader, JsonTypeInfo.ObjectType, Options); dictionary[state.Current.JsonPropertyNameAsString] = value; } } else { IDictionary<string, JsonElement> dictionary2 = valueAsObject as IDictionary<string, JsonElement>; if (dictionary2 != null) { JsonElement value2 = <ReadJsonAndAddExtensionProperty>g__GetDictionaryValueConverter|143_0<JsonElement>().Read(ref reader, typeof(JsonElement), Options); dictionary2[state.Current.JsonPropertyNameAsString] = value2; } else EffectiveConverter.ReadElementAndSetProperty(valueAsObject, state.Current.JsonPropertyNameAsString, ref reader, Options, ref state); } return true; } internal abstract bool ReadJsonAndSetMember(object obj, [System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, ref Utf8JsonReader reader); internal abstract bool ReadJsonAsObject([System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, ref Utf8JsonReader reader, out object value); internal bool ReadJsonExtensionDataValue([System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, ref Utf8JsonReader reader, out object value) { if (JsonTypeInfo.ElementType == JsonTypeInfo.ObjectType && reader.TokenType == JsonTokenType.Null) { value = null; return true; } if (!((JsonConverter<JsonElement>)Options.GetConverterInternal(typeof(JsonElement))).TryRead(ref reader, typeof(JsonElement), Options, ref state, out JsonElement value2, out bool _)) { value = null; return false; } value = value2; return true; } internal void EnsureChildOf(JsonTypeInfo parent) { if (DeclaringTypeInfo == null) DeclaringTypeInfo = parent; else if (DeclaringTypeInfo != parent) { ThrowHelper.ThrowInvalidOperationException_JsonPropertyInfoIsBoundToDifferentJsonTypeInfo(this); } DeclaringTypeInfo.ResolveMatchingParameterInfo(this); } internal bool TryGetPrePopulatedValue([System.Runtime.CompilerServices.ScopedRef] ref ReadStack state) { if (EffectiveObjectCreationHandling != JsonObjectCreationHandling.Populate) return false; object obj = Get(state.Parent.ReturnValue); state.Current.ReturnValue = obj; state.Current.IsPopulating = (obj != null); return obj != null; } internal bool IsOverriddenOrShadowedBy(JsonPropertyInfo other) { if (MemberName == other.MemberName) return DeclaringType.IsAssignableFrom(other.DeclaringType); return false; } } }