< Summary

Information
Class: System.Text.Json.Serialization.Metadata.JsonPropertyInfo
Assembly: System.Text.Json
File(s): C:\h\w\B31A098C\w\BB5A0A33\e\runtime-utils\Runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Serialization\Metadata\JsonPropertyInfo.cs
Line coverage
55%
Covered lines: 266
Uncovered lines: 216
Coverable lines: 482
Total lines: 1098
Line coverage: 55.1%
Branch coverage
45%
Covered branches: 116
Total branches: 256
Branch coverage: 45.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

C:\h\w\B31A098C\w\BB5A0A33\e\runtime-utils\Runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Serialization\Metadata\JsonPropertyInfo.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Collections.Generic;
 5using System.Diagnostics;
 6using System.Diagnostics.CodeAnalysis;
 7using System.Reflection;
 8using System.Threading;
 9
 10namespace System.Text.Json.Serialization.Metadata
 11{
 12    /// <summary>
 13    /// Provides JSON serialization-related metadata about a property or field defined in an object.
 14    /// </summary>
 15    [DebuggerDisplay("{DebuggerDisplay,nq}")]
 16    public abstract class JsonPropertyInfo
 17    {
 018        internal static readonly JsonPropertyInfo s_missingProperty = GetPropertyPlaceholder();
 19
 26228520        internal JsonTypeInfo? DeclaringTypeInfo { get; private set; }
 21
 22        /// <summary>
 23        /// Converter after applying CustomConverter (i.e. JsonConverterAttribute)
 24        /// </summary>
 25        internal JsonConverter EffectiveConverter
 26        {
 27            get
 13247428            {
 13247429                Debug.Assert(_effectiveConverter != null);
 13247430                return _effectiveConverter;
 13247431            }
 32        }
 33
 34        private protected JsonConverter? _effectiveConverter;
 35
 36        /// <summary>
 37        /// Gets or sets a custom converter override for the current property.
 38        /// </summary>
 39        /// <exception cref="InvalidOperationException">
 40        /// The <see cref="JsonPropertyInfo"/> instance has been locked for further modification.
 41        /// </exception>
 42        /// <remarks>
 43        /// It is possible to use <see cref="JsonConverterFactory"/> instances with this property.
 44        ///
 45        /// For contracts originating from <see cref="DefaultJsonTypeInfoResolver"/>, the value of
 46        /// <see cref="CustomConverter"/> will be mapped from <see cref="JsonConverterAttribute" /> annotations.
 47        /// </remarks>
 48        public JsonConverter? CustomConverter
 49        {
 2004850            get => _customConverter;
 51            set
 779452            {
 779453                VerifyMutable();
 779454                _customConverter = value;
 779455            }
 56        }
 57
 58        private JsonConverter? _customConverter;
 59
 60        /// <summary>
 61        /// Gets or sets a getter delegate for the property.
 62        /// </summary>
 63        /// <exception cref="InvalidOperationException">
 64        /// The <see cref="JsonPropertyInfo"/> instance has been locked for further modification.
 65        /// </exception>
 66        /// <remarks>
 67        /// Setting to <see langword="null"/> will result in the property being skipped on serialization.
 68        /// </remarks>
 69        public Func<object, object?>? Get
 70        {
 779471            get => _untypedGet;
 72            set
 073            {
 074                VerifyMutable();
 075                SetGetter(value);
 076            }
 77        }
 78
 79        /// <summary>
 80        /// Gets or sets a setter delegate for the property.
 81        /// </summary>
 82        /// <exception cref="InvalidOperationException">
 83        /// The <see cref="JsonPropertyInfo"/> instance has been locked for further modification.
 84        /// </exception>
 85        /// <remarks>
 86        /// Setting to <see langword="null"/> will result in the property being skipped on deserialization.
 87        /// </remarks>
 88        public Action<object, object?>? Set
 89        {
 695790            get => _untypedSet;
 91            set
 092            {
 093                VerifyMutable();
 094                SetSetter(value);
 095                _isUserSpecifiedSetter = true;
 096            }
 97        }
 98
 99        private protected Func<object, object?>? _untypedGet;
 100        private protected Action<object, object?>? _untypedSet;
 101        private bool _isUserSpecifiedSetter;
 102
 103        private protected abstract void SetGetter(Delegate? getter);
 104        private protected abstract void SetSetter(Delegate? setter);
 105
 106        /// <summary>
 107        /// Gets or sets a predicate deciding whether the current property value should be serialized.
 108        /// </summary>
 109        /// <exception cref="InvalidOperationException">
 110        /// The <see cref="JsonPropertyInfo"/> instance has been locked for further modification.
 111        /// </exception>
 112        /// <remarks>
 113        /// The first parameter denotes the parent object, the second parameter denotes the property value.
 114        ///
 115        /// Setting the predicate to <see langword="null"/> is equivalent to always serializing the property value.
 116        ///
 117        /// For contracts originating from <see cref="DefaultJsonTypeInfoResolver"/>,
 118        /// the value of <see cref="JsonIgnoreAttribute.Condition"/> will map to this predicate.
 119        /// </remarks>
 120        public Func<object, object?, bool>? ShouldSerialize
 121        {
 0122            get => _shouldSerialize;
 123            set
 0124            {
 0125                VerifyMutable();
 0126                SetShouldSerialize(value);
 127                // Invalidate any JsonIgnore configuration if delegate set manually by user
 0128                _isUserSpecifiedShouldSerialize = true;
 0129                IgnoreDefaultValuesOnWrite = false;
 0130            }
 131        }
 132
 133        private protected Func<object, object?, bool>? _shouldSerialize;
 134        private bool _isUserSpecifiedShouldSerialize;
 135        private protected abstract void SetShouldSerialize(Delegate? predicate);
 136
 137        internal JsonIgnoreCondition? IgnoreCondition
 138        {
 0139            get => _ignoreCondition;
 140            set
 7794141            {
 7794142                Debug.Assert(!IsConfigured);
 7794143                ConfigureIgnoreCondition(value);
 7794144                _ignoreCondition = value;
 7794145            }
 146        }
 147
 148        private JsonIgnoreCondition? _ignoreCondition;
 149        private protected abstract void ConfigureIgnoreCondition(JsonIgnoreCondition? ignoreCondition);
 150
 151        /// <summary>
 152        /// Gets or sets a custom attribute provider for the current property.
 153        /// </summary>
 154        /// <exception cref="InvalidOperationException">
 155        /// The <see cref="JsonPropertyInfo"/> instance has been locked for further modification.
 156        /// </exception>
 157        /// <remarks>
 158        /// When resolving metadata via the built-in resolvers this
 159        /// will be populated with the underlying <see cref="MemberInfo" /> of the serialized property or field.
 160        ///
 161        /// Setting a custom attribute provider will have no impact on the contract model,
 162        /// but serves as metadata for downstream contract modifiers.
 163        /// </remarks>
 164        public ICustomAttributeProvider? AttributeProvider
 165        {
 166            get
 7794167            {
 7794168                Func<ICustomAttributeProvider>? attributeProviderFactory = Volatile.Read(ref AttributeProviderFactory);
 7794169                ICustomAttributeProvider? attributeProvider = _attributeProvider;
 170
 7794171                if (attributeProvider is null && attributeProviderFactory is not null)
 0172                {
 0173                    _attributeProvider = attributeProvider = attributeProviderFactory();
 0174                    Volatile.Write(ref AttributeProviderFactory, null);
 0175                }
 176
 7794177                return attributeProvider;
 7794178            }
 179            set
 7794180            {
 7794181                VerifyMutable();
 182
 7794183                _attributeProvider = value;
 7794184                Volatile.Write(ref AttributeProviderFactory, null);
 7794185            }
 186        }
 187
 188        // Metadata emanating from the source generator use delayed attribute provider initialization
 189        // ensuring that reflection metadata resolution remains pay-for-play and is trimmable.
 190        internal Func<ICustomAttributeProvider>? AttributeProviderFactory;
 191        private ICustomAttributeProvider? _attributeProvider;
 192
 193        /// <summary>
 194        /// Gets or sets a value indicating if the property or field should be replaced or populated during deserializat
 195        /// </summary>
 196        /// <remarks>
 197        /// Initial value for this property is based on the presence of <see cref="JsonObjectCreationHandlingAttribute"/
 198        /// When <see langword="null"/> effective handling will be resolved based on
 199        /// capability of property converter to populate, containing type's <see cref="JsonTypeInfo.PreferredPropertyObj
 200        /// and <see cref="JsonSerializerOptions.PreferredObjectCreationHandling"/> value.
 201        /// </remarks>
 202        public JsonObjectCreationHandling? ObjectCreationHandling
 203        {
 20048204            get => _objectCreationHandling;
 205            set
 7794206            {
 7794207                VerifyMutable();
 208
 7794209                if (value != null)
 0210                {
 0211                    if (!JsonSerializer.IsValidCreationHandlingValue(value.Value))
 0212                    {
 0213                        throw new ArgumentOutOfRangeException(nameof(value));
 214                    }
 0215                }
 216
 7794217                _objectCreationHandling = value;
 7794218            }
 219        }
 220
 221        private JsonObjectCreationHandling? _objectCreationHandling;
 32302222        internal JsonObjectCreationHandling EffectiveObjectCreationHandling { get; private set; }
 223
 32370224        internal string? MemberName { get; set; } // Do not rename (legacy schema generation)
 50550225        internal MemberTypes MemberType { get; set; }
 7794226        internal bool IsVirtual { get; set; }
 227
 228        /// <summary>
 229        /// Gets or sets a value indicating whether the return type of the getter is annotated as nullable.
 230        /// </summary>
 231        /// <exception cref="InvalidOperationException">
 232        /// The <see cref="JsonPropertyInfo"/> instance has been locked for further modification.
 233        ///
 234        /// -or-
 235        ///
 236        /// The current <see cref="PropertyType"/> is not a reference type or <see cref="Nullable{T}"/>.
 237        /// </exception>
 238        /// <remarks>
 239        /// Contracts originating from <see cref="DefaultJsonTypeInfoResolver"/> or <see cref="JsonSerializerContext"/>,
 240        /// derive the value of this property from nullable reference type annotations, including annotations
 241        /// from attributes such as <see cref="NotNullAttribute"/> or <see cref="MaybeNullAttribute"/>.
 242        ///
 243        /// This property has no effect on serialization unless the <see cref="JsonSerializerOptions.RespectNullableAnno
 244        /// property has been enabled, in which case the serializer will reject any <see langword="null"/> values return
 245        /// </remarks>
 246        public bool IsGetNullable
 247        {
 0248            get => _isGetNullable;
 249            set
 2660250            {
 2660251                VerifyMutable();
 252
 2660253                if (value && !PropertyTypeCanBeNull)
 0254                {
 0255                    ThrowHelper.ThrowInvalidOperationException_PropertyTypeNotNullable(this);
 256                }
 257
 2660258                _isGetNullable = value;
 2660259            }
 260        }
 261
 262        private bool _isGetNullable;
 263
 264        /// <summary>
 265        /// Gets or sets a value indicating whether the input type of the setter is annotated as nullable.
 266        /// </summary>
 267        /// <exception cref="InvalidOperationException">
 268        /// The <see cref="JsonPropertyInfo"/> instance has been locked for further modification.
 269        ///
 270        /// -or-
 271        ///
 272        /// The current <see cref="PropertyType"/> is not a reference type or <see cref="Nullable{T}"/>.
 273        /// </exception>
 274        /// <remarks>
 275        /// Contracts originating from <see cref="DefaultJsonTypeInfoResolver"/> or <see cref="JsonSerializerContext"/>,
 276        /// derive the value of this property from nullable reference type annotations, including annotations
 277        /// from attributes such as <see cref="AllowNullAttribute"/> or <see cref="DisallowNullAttribute"/>.
 278        ///
 279        /// This property has no effect on deserialization unless the <see cref="JsonSerializerOptions.RespectNullableAn
 280        /// property has been enabled, in which case the serializer will reject any <see langword="null"/> deserializati
 281        ///
 282        /// If the property has been associated with a deserialization constructor parameter,
 283        /// this setting reflected the nullability annotation of the parameter and not the property setter.
 284        /// </remarks>
 285        public bool IsSetNullable
 286        {
 0287            get => _isSetNullable;
 288            set
 2660289            {
 2660290                VerifyMutable();
 291
 2660292                if (value && !PropertyTypeCanBeNull)
 0293                {
 0294                    ThrowHelper.ThrowInvalidOperationException_PropertyTypeNotNullable(this);
 295                }
 296
 2660297                _isSetNullable = value;
 2660298            }
 299        }
 300
 301        private protected bool _isSetNullable;
 302
 303        /// <summary>
 304        /// Specifies whether the current property is a special extension data property.
 305        /// </summary>
 306        /// <exception cref="InvalidOperationException">
 307        /// The <see cref="JsonPropertyInfo"/> instance has been locked for further modification.
 308        ///
 309        /// -or-
 310        ///
 311        /// The current <see cref="PropertyType"/> is not valid for use with extension data.
 312        /// </exception>
 313        /// <remarks>
 314        /// For contracts originating from <see cref="DefaultJsonTypeInfoResolver"/> or <see cref="JsonSerializerContext
 315        /// the value of this property will be mapped from <see cref="JsonExtensionDataAttribute"/> annotations.
 316        /// </remarks>
 317        public bool IsExtensionData
 318        {
 7794319            get => _isExtensionDataProperty;
 320            set
 7794321            {
 7794322                VerifyMutable();
 323
 7794324                if (value && !JsonTypeInfo.IsValidExtensionDataProperty(PropertyType))
 0325                {
 0326                    ThrowHelper.ThrowInvalidOperationException_SerializationDataExtensionPropertyInvalid(this);
 327                }
 328
 7794329                _isExtensionDataProperty = value;
 7794330            }
 331        }
 332
 333        private bool _isExtensionDataProperty;
 334
 335        /// <summary>
 336        /// Specifies whether the current property is required for deserialization to be successful.
 337        /// </summary>
 338        /// <exception cref="InvalidOperationException">
 339        /// The <see cref="JsonPropertyInfo"/> instance has been locked for further modification.
 340        /// </exception>
 341        /// <remarks>
 342        /// For contracts originating from <see cref="DefaultJsonTypeInfoResolver"/> or <see cref="JsonSerializerContext
 343        /// the value of this property will be mapped from <see cref="JsonRequiredAttribute"/> annotations.
 344        ///
 345        /// For contracts using <see cref="DefaultJsonTypeInfoResolver"/>, properties using the <see langword="required"
 346        /// will also map to this setting, unless deserialization uses a SetsRequiredMembersAttribute on a constructor t
 347        /// <see langword="required"/> keyword is currently not supported in <see cref="JsonSerializerContext"/> contrac
 348        /// </remarks>
 349        public bool IsRequired
 350        {
 27842351            get => _isRequired;
 352            set
 7794353            {
 7794354                VerifyMutable();
 7794355                _isRequired = value;
 7794356            }
 357        }
 358
 359        private protected bool _isRequired;
 360
 361        /// <summary>
 362        /// Gets the constructor parameter associated with the current property.
 363        /// </summary>
 364        /// <remarks>
 365        /// Returns the <see cref="JsonParameterInfo"/> metadata for the parameter in the
 366        /// deserialization constructor that has been associated with the current property.
 367        ///
 368        /// A constructor parameter is matched to a property or field if they are of the
 369        /// same type and have the same name, up to case insensitivity. Each constructor
 370        /// parameter must be matched to exactly one property of field.
 371        /// </remarks>
 13482372        public JsonParameterInfo? AssociatedParameter { get; internal set; }
 373
 20048374        internal JsonPropertyInfo(Type declaringType, Type propertyType, JsonTypeInfo? declaringTypeInfo, JsonSerializer
 20048375        {
 20048376            Debug.Assert(declaringTypeInfo is null || declaringType.IsAssignableFrom(declaringTypeInfo.Type));
 377
 20048378            DeclaringType = declaringType;
 20048379            PropertyType = propertyType;
 20048380            DeclaringTypeInfo = declaringTypeInfo; // null declaringTypeInfo means it's not tied yet
 20048381            Options = options;
 382
 20048383            _isGetNullable = _isSetNullable = PropertyTypeCanBeNull;
 20048384        }
 385
 386        internal static JsonPropertyInfo GetPropertyPlaceholder()
 0387        {
 0388            JsonPropertyInfo info = new JsonPropertyInfo<object>(typeof(object), declaringTypeInfo: null, options: null!
 389
 0390            Debug.Assert(!info.IsForTypeInfo);
 0391            Debug.Assert(!info.CanSerialize);
 0392            Debug.Assert(!info.CanDeserialize);
 393
 0394            info.Name = string.Empty;
 395
 0396            return info;
 0397        }
 398
 399        /// <summary>
 400        /// Gets the declaring type of the property.
 401        /// </summary>
 0402        public Type DeclaringType { get; }
 403
 404        /// <summary>
 405        /// Gets the type of the current property.
 406        /// </summary>
 81794407        public Type PropertyType { get; }
 408
 409        private protected void VerifyMutable()
 67672410        {
 67672411            DeclaringTypeInfo?.VerifyMutable();
 67672412        }
 413
 128150414        internal bool IsConfigured { get; private set; }
 415
 416        internal void Configure()
 20048417        {
 20048418            Debug.Assert(DeclaringTypeInfo != null);
 20048419            Debug.Assert(!IsConfigured);
 420
 20048421            if (IsIgnored)
 0422            {
 423                // Avoid configuring JsonIgnore.Always properties
 424                // to avoid failing on potentially unsupported types.
 0425                CanSerialize = false;
 0426                CanDeserialize = false;
 0427            }
 428            else
 20048429            {
 20048430                _jsonTypeInfo ??= Options.GetTypeInfoInternal(PropertyType);
 20048431                _jsonTypeInfo.EnsureConfigured();
 432
 20048433                DetermineEffectiveConverter(_jsonTypeInfo);
 20048434                DetermineNumberHandlingForProperty();
 20048435                DetermineEffectiveObjectCreationHandlingForProperty();
 20048436                DetermineSerializationCapabilities();
 20048437                DetermineIgnoreCondition();
 20048438            }
 439
 20048440            if (IsForTypeInfo)
 12254441            {
 12254442                DetermineNumberHandlingForTypeInfo();
 12254443            }
 444            else
 7794445            {
 7794446                ValidateAndCachePropertyName();
 7794447            }
 448
 20048449            if (IsRequired)
 0450            {
 0451                if (!CanDeserialize &&
 0452                    !(AssociatedParameter?.IsRequiredParameter is true &&
 0453                      Options.RespectRequiredConstructorParameters))
 0454                {
 0455                    ThrowHelper.ThrowInvalidOperationException_JsonPropertyRequiredAndNotDeserializable(this);
 456                }
 457
 0458                if (IsExtensionData)
 0459                {
 0460                    ThrowHelper.ThrowInvalidOperationException_JsonPropertyRequiredAndExtensionData(this);
 461                }
 462
 0463                Debug.Assert(!IgnoreNullTokensOnRead);
 0464            }
 465
 20048466            IsConfigured = true;
 20048467        }
 468
 469        private protected abstract void DetermineEffectiveConverter(JsonTypeInfo jsonTypeInfo);
 470
 471        [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
 472        [RequiresDynamicCode(JsonSerializer.SerializationRequiresDynamicCodeMessage)]
 473        internal abstract void DetermineReflectionPropertyAccessors(MemberInfo memberInfo, bool useNonPublicAccessors);
 474
 475        private void ValidateAndCachePropertyName()
 7794476        {
 7794477            Debug.Assert(Name != null);
 478
 7794479            if (Options.ReferenceHandlingStrategy is JsonKnownReferenceHandler.Preserve &&
 7794480                this is { DeclaringType.IsValueType: false, IsIgnored: false, IsExtensionData: false } &&
 7794481                Name is JsonSerializer.IdPropertyName or JsonSerializer.RefPropertyName)
 0482            {
 483                // Validate potential conflicts with reference preservation metadata property names.
 484                // Conflicts with polymorphic type discriminators are contextual and need to be
 485                // handled separately by the PolymorphicTypeResolver type.
 486
 0487                ThrowHelper.ThrowInvalidOperationException_PropertyConflictsWithMetadataPropertyName(DeclaringType, Name
 488            }
 489
 7794490            NameAsUtf8Bytes = Encoding.UTF8.GetBytes(Name);
 7794491            EscapedNameSection = JsonHelpers.GetEscapedPropertyNameSection(NameAsUtf8Bytes, Options.Encoder);
 7794492        }
 493
 494        private void DetermineIgnoreCondition()
 20048495        {
 20048496            if (_ignoreCondition != null)
 0497            {
 498                // Do not apply global policy if already configured on the property level.
 0499                return;
 500            }
 501
 502#pragma warning disable SYSLIB0020 // JsonSerializerOptions.IgnoreNullValues is obsolete
 20048503            if (Options.IgnoreNullValues)
 504#pragma warning restore SYSLIB0020
 0505            {
 0506                Debug.Assert(Options.DefaultIgnoreCondition == JsonIgnoreCondition.Never);
 0507                if (PropertyTypeCanBeNull)
 0508                {
 0509                    IgnoreNullTokensOnRead = !_isUserSpecifiedSetter && !IsRequired;
 0510                    IgnoreDefaultValuesOnWrite = ShouldSerialize is null;
 0511                }
 0512            }
 20048513            else if (Options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingNull)
 0514            {
 0515                if (PropertyTypeCanBeNull)
 0516                {
 0517                    IgnoreDefaultValuesOnWrite = ShouldSerialize is null;
 0518                }
 0519            }
 20048520            else if (Options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingDefault)
 0521            {
 0522                IgnoreDefaultValuesOnWrite = ShouldSerialize is null;
 0523            }
 20048524        }
 525
 526        private void DetermineSerializationCapabilities()
 20048527        {
 20048528            Debug.Assert(EffectiveConverter != null, "Must have calculated the effective converter.");
 20048529            CanSerialize = HasGetter;
 20048530            CanDeserialize = HasSetter;
 531
 20048532            Debug.Assert(MemberType is 0 or MemberTypes.Field or MemberTypes.Property);
 20048533            if (MemberType == 0 || _ignoreCondition != null)
 12254534            {
 535                // No policy to be applied if either:
 536                // 1. JsonPropertyInfo is a custom instance (not generated via reflection or sourcegen).
 537                // 2. A JsonIgnoreCondition has been specified on the property level.
 12254538                CanDeserializeOrPopulate = CanDeserialize || EffectiveObjectCreationHandling == JsonObjectCreationHandli
 12254539                return;
 540            }
 541
 7794542            if ((EffectiveConverter.ConverterStrategy & (ConverterStrategy.Enumerable | ConverterStrategy.Dictionary)) !
 837543            {
 544                // Properties of collections types that only have setters are not supported.
 837545                if (Get == null && Set != null && !_isUserSpecifiedSetter)
 0546                {
 0547                    CanDeserialize = false;
 0548                }
 837549            }
 550            else
 6957551            {
 552                // For read-only properties of non-collection types, apply IgnoreReadOnlyProperties/Fields policy,
 553                // unless a `ShouldSerialize` predicate has been explicitly applied by the user (null or non-null).
 6957554                if (Get != null && Set == null && IgnoreReadOnlyMember && !_isUserSpecifiedShouldSerialize)
 0555                {
 0556                    CanSerialize = false;
 0557                }
 6957558            }
 559
 7794560            CanDeserializeOrPopulate = CanDeserialize || EffectiveObjectCreationHandling == JsonObjectCreationHandling.P
 20048561        }
 562
 563        private void DetermineNumberHandlingForTypeInfo()
 12254564        {
 12254565            Debug.Assert(DeclaringTypeInfo != null, "We should have ensured parent is assigned in JsonTypeInfo");
 12254566            Debug.Assert(!DeclaringTypeInfo.IsConfigured);
 567
 12254568            JsonNumberHandling? declaringTypeNumberHandling = DeclaringTypeInfo.NumberHandling;
 569
 12254570            if (declaringTypeNumberHandling != null && declaringTypeNumberHandling != JsonNumberHandling.Strict && !Effe
 0571            {
 0572                ThrowHelper.ThrowInvalidOperationException_NumberHandlingOnPropertyInvalid(this);
 573            }
 574
 12254575            if (NumberHandingIsApplicable())
 4691576            {
 577                // This logic is to honor JsonNumberHandlingAttribute placed on
 578                // custom collections e.g. public class MyNumberList : List<int>.
 579
 580                // Priority 1: Get handling from the type (parent type in this case is the type itself).
 4691581                EffectiveNumberHandling = declaringTypeNumberHandling;
 582
 583                // Priority 2: Get handling from JsonSerializerOptions instance.
 4691584                if (!EffectiveNumberHandling.HasValue && Options.NumberHandling != JsonNumberHandling.Strict)
 3450585                {
 3450586                    EffectiveNumberHandling = Options.NumberHandling;
 3450587                }
 4691588            }
 12254589        }
 590
 591        private void DetermineNumberHandlingForProperty()
 20048592        {
 20048593            Debug.Assert(DeclaringTypeInfo != null, "We should have ensured parent is assigned in JsonTypeInfo");
 20048594            Debug.Assert(!IsConfigured, "Should not be called post-configuration.");
 20048595            Debug.Assert(_jsonTypeInfo != null, "Must have already been determined on configuration.");
 596
 20048597            bool numberHandlingIsApplicable = NumberHandingIsApplicable();
 598
 20048599            if (numberHandlingIsApplicable)
 6387600            {
 601                // Priority 1: Get handling from attribute on property/field, its parent class type or property type.
 6387602                JsonNumberHandling? handling = NumberHandling ?? DeclaringTypeInfo.NumberHandling ?? _jsonTypeInfo.Numbe
 603
 604                // Priority 2: Get handling from JsonSerializerOptions instance.
 6387605                if (!handling.HasValue && Options.NumberHandling != JsonNumberHandling.Strict)
 4637606                {
 4637607                    handling = Options.NumberHandling;
 4637608                }
 609
 6387610                EffectiveNumberHandling = handling;
 6387611            }
 13661612            else if (NumberHandling.HasValue && NumberHandling != JsonNumberHandling.Strict)
 0613            {
 0614                ThrowHelper.ThrowInvalidOperationException_NumberHandlingOnPropertyInvalid(this);
 615            }
 20048616        }
 617
 618        private void DetermineEffectiveObjectCreationHandlingForProperty()
 20048619        {
 20048620            Debug.Assert(EffectiveConverter != null, "Must have calculated the effective converter.");
 20048621            Debug.Assert(DeclaringTypeInfo != null, "We should have ensured parent is assigned in JsonTypeInfo");
 20048622            Debug.Assert(!IsConfigured, "Should not be called post-configuration.");
 623
 20048624            JsonObjectCreationHandling effectiveObjectCreationHandling = JsonObjectCreationHandling.Replace;
 20048625            if (ObjectCreationHandling == null)
 20048626            {
 627                // Consult type-level configuration, then global configuration.
 628                // Ignore global configuration if we're using a parameterized constructor.
 20048629                JsonObjectCreationHandling preferredCreationHandling =
 20048630                    DeclaringTypeInfo.PreferredPropertyObjectCreationHandling
 20048631                    ?? (DeclaringTypeInfo.DetermineUsesParameterizedConstructor()
 20048632                        ? JsonObjectCreationHandling.Replace
 20048633                        : Options.PreferredObjectCreationHandling);
 634
 20048635                bool canPopulate =
 20048636                    preferredCreationHandling == JsonObjectCreationHandling.Populate &&
 20048637                    EffectiveConverter.CanPopulate &&
 20048638                    Get != null &&
 20048639                    (!PropertyType.IsValueType || Set != null) &&
 20048640                    !DeclaringTypeInfo.SupportsPolymorphicDeserialization &&
 20048641                    !(Set == null && IgnoreReadOnlyMember);
 642
 20048643                effectiveObjectCreationHandling = canPopulate ? JsonObjectCreationHandling.Populate : JsonObjectCreation
 20048644            }
 0645            else if (ObjectCreationHandling == JsonObjectCreationHandling.Populate)
 0646            {
 0647                if (!EffectiveConverter.CanPopulate)
 0648                {
 0649                    ThrowHelper.ThrowInvalidOperationException_ObjectCreationHandlingPopulateNotSupportedByConverter(thi
 650                }
 651
 0652                if (Get == null)
 0653                {
 0654                    ThrowHelper.ThrowInvalidOperationException_ObjectCreationHandlingPropertyMustHaveAGetter(this);
 655                }
 656
 0657                if (PropertyType.IsValueType && Set == null)
 0658                {
 0659                    ThrowHelper.ThrowInvalidOperationException_ObjectCreationHandlingPropertyValueTypeMustHaveASetter(th
 660                }
 661
 0662                Debug.Assert(_jsonTypeInfo != null);
 0663                Debug.Assert(_jsonTypeInfo.IsConfigurationStarted);
 0664                if (JsonTypeInfo.SupportsPolymorphicDeserialization)
 0665                {
 0666                    ThrowHelper.ThrowInvalidOperationException_ObjectCreationHandlingPropertyCannotAllowPolymorphicDeser
 667                }
 668
 0669                if (Set == null && IgnoreReadOnlyMember)
 0670                {
 0671                    ThrowHelper.ThrowInvalidOperationException_ObjectCreationHandlingPropertyCannotAllowReadOnlyMember(t
 672                }
 673
 0674                effectiveObjectCreationHandling = JsonObjectCreationHandling.Populate;
 0675            }
 676
 20048677            if (effectiveObjectCreationHandling is JsonObjectCreationHandling.Populate)
 0678            {
 0679                if (DeclaringTypeInfo.DetermineUsesParameterizedConstructor())
 0680                {
 0681                    ThrowHelper.ThrowNotSupportedException_ObjectCreationHandlingPropertyDoesNotSupportParameterizedCons
 682                }
 683
 0684                if (Options.ReferenceHandlingStrategy != JsonKnownReferenceHandler.Unspecified)
 0685                {
 0686                    ThrowHelper.ThrowInvalidOperationException_ObjectCreationHandlingPropertyCannotAllowReferenceHandlin
 687                }
 0688            }
 689
 690            // Validation complete, commit configuration.
 20048691            EffectiveObjectCreationHandling = effectiveObjectCreationHandling;
 20048692        }
 693
 694        private bool NumberHandingIsApplicable()
 32302695        {
 32302696            if (EffectiveConverter.IsInternalConverterForNumberType)
 9002697            {
 9002698                return true;
 699            }
 700
 701            Type potentialNumberType;
 23300702            if (!EffectiveConverter.IsInternalConverter ||
 23300703                ((ConverterStrategy.Enumerable | ConverterStrategy.Dictionary) & EffectiveConverter.ConverterStrategy) =
 20459704            {
 20459705                potentialNumberType = PropertyType;
 20459706            }
 707            else
 2841708            {
 2841709                Debug.Assert(EffectiveConverter.ElementType != null);
 2841710                potentialNumberType = EffectiveConverter.ElementType;
 2841711            }
 712
 23300713            potentialNumberType = Nullable.GetUnderlyingType(potentialNumberType) ?? potentialNumberType;
 714
 23300715            return potentialNumberType == typeof(byte) ||
 23300716                potentialNumberType == typeof(decimal) ||
 23300717                potentialNumberType == typeof(double) ||
 23300718                potentialNumberType == typeof(short) ||
 23300719                potentialNumberType == typeof(int) ||
 23300720                potentialNumberType == typeof(long) ||
 23300721                potentialNumberType == typeof(sbyte) ||
 23300722                potentialNumberType == typeof(float) ||
 23300723                potentialNumberType == typeof(ushort) ||
 23300724                potentialNumberType == typeof(uint) ||
 23300725                potentialNumberType == typeof(ulong) ||
 23300726#if NET
 23300727                potentialNumberType == typeof(Half) ||
 23300728#endif
 23300729#if NET
 23300730                potentialNumberType == typeof(Int128) ||
 23300731                potentialNumberType == typeof(UInt128) ||
 23300732#endif
 23300733                potentialNumberType == JsonTypeInfo.ObjectType;
 32302734        }
 735
 736        /// <summary>
 737        /// Creates a <see cref="JsonPropertyInfo"/> instance whose type matches that of the current property.
 738        /// </summary>
 739        internal abstract void AddJsonParameterInfo(JsonParameterInfoValues parameterInfoValues);
 740
 741        internal abstract bool GetMemberAndWriteJson(object obj, ref WriteStack state, Utf8JsonWriter writer);
 742        internal abstract bool GetMemberAndWriteJsonExtensionData(object obj, ref WriteStack state, Utf8JsonWriter write
 743
 744        internal abstract object? GetValueAsObject(object obj);
 745
 20048746        internal bool HasGetter => _untypedGet is not null;
 20048747        internal bool HasSetter => _untypedSet is not null;
 0748        internal bool IgnoreNullTokensOnRead { get; private protected set; }
 0749        internal bool IgnoreDefaultValuesOnWrite { get; private protected set; }
 750
 751        internal bool IgnoreReadOnlyMember
 752        {
 753            get
 0754            {
 0755                Debug.Assert(MemberType == MemberTypes.Property || MemberType == MemberTypes.Field || MemberType == defa
 0756                return MemberType switch
 0757                {
 0758                    MemberTypes.Property => Options.IgnoreReadOnlyProperties,
 0759                    MemberTypes.Field => Options.IgnoreReadOnlyFields,
 0760                    _ => false,
 0761                };
 0762            }
 763        }
 764
 765        /// <summary>
 766        /// True if the corresponding cref="JsonTypeInfo.PropertyInfoForTypeInfo"/> is this instance.
 767        /// </summary>
 32306768        internal bool IsForTypeInfo { get; init; }
 769
 770        // There are 3 copies of the property name:
 771        // 1) Name. The unescaped property name.
 772        // 2) NameAsUtf8Bytes. The Utf8 version of Name. Used during deserialization for property lookup.
 773        // 3) EscapedNameSection. The escaped version of NameAsUtf8Bytes plus the wrapping quotes and a trailing colon. 
 774
 775        /// <summary>
 776        /// Gets or sets the JSON property name used when serializing the property.
 777        /// </summary>
 778        /// <exception cref="ArgumentNullException"><paramref name="value"/> is null.</exception>
 779        /// <exception cref="InvalidOperationException">
 780        /// The <see cref="JsonPropertyInfo"/> instance has been locked for further modification.
 781        /// </exception>
 782        /// <remarks>
 783        /// The value of <see cref="Name"/> cannot conflict with that of other <see cref="JsonPropertyInfo"/> defined in
 784        ///
 785        /// For contracts originating from <see cref="DefaultJsonTypeInfoResolver"/> or <see cref="JsonSerializerContext
 786        /// the value typically reflects the underlying .NET member name, the name derived from <see cref="JsonSerialize
 787        /// or the value specified in <see cref="JsonPropertyNameAttribute" />.
 788        /// </remarks>
 789        public string Name
 790        {
 791            get
 38970792            {
 38970793                Debug.Assert(_name != null);
 38970794                return _name;
 38970795            }
 796            set
 7794797            {
 7794798                VerifyMutable();
 799
 7794800                ArgumentNullException.ThrowIfNull(value);
 801
 7794802                _name = value;
 7794803            }
 804        }
 805
 806        private string? _name;
 807
 808        /// <summary>
 809        /// Utf8 version of Name.
 810        /// </summary>
 93134811        internal byte[] NameAsUtf8Bytes { get; private set; } = null!;
 812
 813        /// <summary>
 814        /// The escaped name passed to the writer.
 815        /// </summary>
 27842816        internal byte[] EscapedNameSection { get; private set; } = null!;
 817
 818        /// <summary>
 819        /// Gets the <see cref="JsonSerializerOptions"/> value associated with the current contract instance.
 820        /// </summary>
 143395821        public JsonSerializerOptions Options { get; }
 822
 823        /// <summary>
 824        /// Gets or sets the serialization order for the current property.
 825        /// </summary>
 826        /// <exception cref="InvalidOperationException">
 827        /// The <see cref="JsonPropertyInfo"/> instance has been locked for further modification.
 828        /// </exception>
 829        /// <remarks>
 830        /// For contracts originating from <see cref="DefaultJsonTypeInfoResolver"/> or <see cref="JsonSerializerContext
 831        /// the value of this property will be mapped from <see cref="JsonPropertyOrderAttribute"/> annotations.
 832        /// </remarks>
 833        public int Order
 834        {
 23382835            get => _order;
 836            set
 7794837            {
 7794838                VerifyMutable();
 7794839                _order = value;
 7794840            }
 841        }
 842
 843        private int _order;
 844
 845        internal bool ReadJsonAndAddExtensionProperty(
 846            object obj,
 847            scoped ref ReadStack state,
 848            ref Utf8JsonReader reader)
 0849        {
 0850            object propValue = GetValueAsObject(obj)!;
 851
 0852            if (propValue is IDictionary<string, object?> dictionaryObjectValue)
 0853            {
 0854                if (reader.TokenType == JsonTokenType.Null)
 0855                {
 856                    // A null JSON value is treated as a null object reference.
 0857                    AddProperty(in state.Current, dictionaryObjectValue, null);
 0858                }
 859                else
 0860                {
 0861                    JsonConverter<object> converter = GetDictionaryValueConverter<object>();
 0862                    object value = converter.Read(ref reader, JsonTypeInfo.ObjectType, Options)!;
 0863                    AddProperty(in state.Current, dictionaryObjectValue, value);
 0864                }
 0865            }
 0866            else if (propValue is IDictionary<string, JsonElement> dictionaryElementValue)
 0867            {
 0868                JsonConverter<JsonElement> converter = GetDictionaryValueConverter<JsonElement>();
 0869                JsonElement value = converter.Read(ref reader, typeof(JsonElement), Options);
 0870                AddProperty(in state.Current, dictionaryElementValue, value);
 0871            }
 872            else
 0873            {
 874                // Avoid a type reference to JsonObject and its converter to support trimming.
 0875                Debug.Assert(propValue is Nodes.JsonObject);
 0876                EffectiveConverter.ReadElementAndSetProperty(propValue, state.Current.JsonPropertyNameAsString!, ref rea
 0877            }
 878
 0879            return true;
 880
 881            JsonConverter<TValue> GetDictionaryValueConverter<TValue>()
 0882            {
 0883                JsonTypeInfo dictionaryValueInfo =
 0884                    JsonTypeInfo.ElementTypeInfo
 0885                    // Slower path for non-generic types that implement IDictionary<,>.
 0886                    // It is possible to cache this converter on JsonTypeInfo if we assume the property value
 0887                    // will always be the same type for all instances.
 0888                    ?? Options.GetTypeInfoInternal(typeof(TValue));
 889
 0890                Debug.Assert(dictionaryValueInfo is JsonTypeInfo<TValue>);
 0891                return ((JsonTypeInfo<TValue>)dictionaryValueInfo).EffectiveConverter;
 0892            }
 893
 894            void AddProperty<TValue>(ref readonly ReadStackFrame current, IDictionary<string, TValue> d, TValue value)
 0895            {
 0896                string property = current.JsonPropertyNameAsString!;
 0897                if (Options.AllowDuplicateProperties)
 0898                {
 0899                    d[property] = value;
 0900                }
 901                else
 0902                {
 903#if NET
 0904                    if (!d.TryAdd(property, value))
 905#else
 906                    if (d.ContainsKey(property))
 907#endif
 0908                    {
 0909                        ThrowHelper.ThrowJsonException_DuplicatePropertyNotAllowed(current.JsonPropertyInfo!);
 910                    }
 911
 912#if !NET
 913                    d[property] = value;
 914#endif
 0915                }
 0916            }
 0917        }
 918
 919        internal abstract bool ReadJsonAndSetMember(object obj, scoped ref ReadStack state, ref Utf8JsonReader reader);
 920
 921        internal abstract bool ReadJsonAsObject(scoped ref ReadStack state, ref Utf8JsonReader reader, out object? value
 922
 923        internal bool ReadJsonExtensionDataValue(scoped ref ReadStack state, ref Utf8JsonReader reader, out object? valu
 0924        {
 0925            Debug.Assert(this == state.Current.JsonTypeInfo.ExtensionDataProperty);
 926
 0927            if (JsonTypeInfo.ElementType == JsonTypeInfo.ObjectType && reader.TokenType == JsonTokenType.Null)
 0928            {
 0929                value = null;
 0930                return true;
 931            }
 932
 0933            JsonConverter<JsonElement> converter = (JsonConverter<JsonElement>)Options.GetConverterInternal(typeof(JsonE
 0934            if (!converter.TryRead(ref reader, typeof(JsonElement), Options, ref state, out JsonElement jsonElement, out
 0935            {
 936                // JsonElement is a struct that must be read in full.
 0937                value = null;
 0938                return false;
 939            }
 940
 0941            value = jsonElement;
 0942            return true;
 0943        }
 944
 945        internal void EnsureChildOf(JsonTypeInfo parent)
 7794946        {
 7794947            if (DeclaringTypeInfo is null)
 0948            {
 0949                DeclaringTypeInfo = parent;
 0950            }
 7794951            else if (DeclaringTypeInfo != parent)
 0952            {
 0953                ThrowHelper.ThrowInvalidOperationException_JsonPropertyInfoIsBoundToDifferentJsonTypeInfo(this);
 954            }
 955
 7794956            DeclaringTypeInfo.ResolveMatchingParameterInfo(this);
 7794957        }
 958
 959        /// <summary>
 960        /// Tries to get pre-populated value from the property if populating is enabled.
 961        /// If property value is <see langword="null"/> this method will return false.
 962        /// </summary>
 963        internal bool TryGetPrePopulatedValue(scoped ref ReadStack state)
 0964        {
 0965            if (EffectiveObjectCreationHandling != JsonObjectCreationHandling.Populate)
 0966                return false;
 967
 0968            Debug.Assert(EffectiveConverter.CanPopulate, "Property is marked with Populate but converter cannot populate
 0969            Debug.Assert(state.Parent.ReturnValue != null, "Parent object is null");
 0970            Debug.Assert(!state.Current.IsPopulating, "We've called TryGetPrePopulatedValue more than once");
 0971            object? value = Get!(state.Parent.ReturnValue);
 0972            state.Current.ReturnValue = value;
 0973            state.Current.IsPopulating = value != null;
 0974            return value != null;
 0975        }
 976
 977        internal JsonTypeInfo JsonTypeInfo
 978        {
 979            get
 7798980            {
 7798981                Debug.Assert(_jsonTypeInfo?.IsConfigurationStarted == true);
 982                // Even though this instance has already been configured,
 983                // it is possible for contending threads to call the property
 984                // while the wider JsonTypeInfo graph is still being configured.
 985                // Call EnsureConfigured() to force synchronization if necessary.
 7798986                JsonTypeInfo jsonTypeInfo = _jsonTypeInfo;
 7798987                jsonTypeInfo.EnsureConfigured();
 7798988                return jsonTypeInfo;
 7798989            }
 990            set
 18691991            {
 18691992                _jsonTypeInfo = value;
 18691993            }
 994        }
 995
 996        private JsonTypeInfo? _jsonTypeInfo;
 997
 998        /// <summary>
 999        /// Returns true if <see cref="JsonTypeInfo"/> has been configured.
 1000        /// This might be false even if <see cref="IsConfigured"/> is true
 1001        /// in cases of recursive types or <see cref="IsIgnored"/> is true.
 1002        /// </summary>
 77941003        internal bool IsPropertyTypeInfoConfigured => _jsonTypeInfo?.IsConfigured == true;
 1004
 1005        /// <summary>
 1006        /// Property was marked JsonIgnoreCondition.Always and also hasn't been configured by the user.
 1007        /// </summary>
 278421008        internal bool IsIgnored => _ignoreCondition is JsonIgnoreCondition.Always && Get is null && Set is null;
 1009
 1010        /// <summary>
 1011        /// Reflects the value of <see cref="HasGetter"/> combined with any additional global ignore policies.
 1012        /// </summary>
 200481013        internal bool CanSerialize { get; private set; }
 1014        /// <summary>
 1015        /// Reflects the value of <see cref="HasSetter"/> combined with any additional global ignore policies.
 1016        /// </summary>
 400961017        internal bool CanDeserialize { get; private set; }
 1018
 1019        /// <summary>
 1020        /// Reflects the value can be deserialized or populated
 1021        /// </summary>
 200481022        internal bool CanDeserializeOrPopulate { get; private set; }
 1023
 1024        /// <summary>
 1025        /// Relevant to source generated metadata: did the property have the <see cref="JsonIncludeAttribute"/>?
 1026        /// </summary>
 01027        internal bool SrcGen_HasJsonInclude { get; set; }
 1028
 1029        /// <summary>
 1030        /// Relevant to source generated metadata: is the property public?
 1031        /// </summary>
 01032        internal bool SrcGen_IsPublic { get; set; }
 1033
 1034        /// <summary>
 1035        /// Gets or sets the <see cref="JsonNumberHandling"/> applied to the current property.
 1036        /// </summary>
 1037        /// <exception cref="InvalidOperationException">
 1038        /// The <see cref="JsonPropertyInfo"/> instance has been locked for further modification.
 1039        /// </exception>
 1040        /// <remarks>
 1041        /// For contracts originating from <see cref="DefaultJsonTypeInfoResolver"/> or <see cref="JsonSerializerContext
 1042        /// the value of this property will be mapped from <see cref="JsonNumberHandlingAttribute"/> annotations.
 1043        /// </remarks>
 1044        public JsonNumberHandling? NumberHandling
 1045        {
 200481046            get => _numberHandling;
 1047            set
 77941048            {
 77941049                VerifyMutable();
 77941050                _numberHandling = value;
 77941051            }
 1052        }
 1053
 1054        private JsonNumberHandling? _numberHandling;
 1055
 1056        /// <summary>
 1057        /// Number handling after considering options and declaring type number handling
 1058        /// </summary>
 751471059        internal JsonNumberHandling? EffectiveNumberHandling { get; private set; }
 1060
 1061        //  Whether the property type can be null.
 1062        internal abstract bool PropertyTypeCanBeNull { get; }
 1063
 1064        /// <summary>
 1065        /// Default value used for parameterized ctor invocation.
 1066        /// </summary>
 1067        internal abstract object? DefaultValue { get; }
 1068
 1069        /// <summary>
 1070        /// Property index on the list of JsonTypeInfo properties.
 1071        /// It is used as a unique identifier for properties.
 1072        /// It is set just before property is configured and does not change afterward.
 1073        /// It is not equivalent to index on the properties list
 1074        /// </summary>
 1075        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
 1076        internal int PropertyIndex
 1077        {
 1078            get
 01079            {
 01080                Debug.Assert(IsConfigured);
 01081                return _propertyIndex;
 01082            }
 1083            set
 77941084            {
 77941085                Debug.Assert(!IsConfigured);
 77941086                _propertyIndex = value;
 77941087            }
 1088        }
 1089
 1090        private int _propertyIndex;
 1091
 1092        internal bool IsOverriddenOrShadowedBy(JsonPropertyInfo other)
 01093            => MemberName == other.MemberName && DeclaringType.IsAssignableFrom(other.DeclaringType);
 1094
 1095        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
 01096        private string DebuggerDisplay => $"Name = {Name}, PropertyType = {PropertyType}";
 1097    }
 1098}

Methods/Properties

.cctor()
DeclaringTypeInfo()
EffectiveConverter()
CustomConverter()
CustomConverter(System.Text.Json.Serialization.JsonConverter)
Get()
Get(System.Func`2<System.Object,System.Object>)
Set()
Set(System.Action`2<System.Object,System.Object>)
ShouldSerialize()
ShouldSerialize(System.Func`3<System.Object,System.Object,System.Boolean>)
IgnoreCondition()
IgnoreCondition(System.Nullable`1<System.Text.Json.Serialization.JsonIgnoreCondition>)
AttributeProvider()
AttributeProvider(System.Reflection.ICustomAttributeProvider)
ObjectCreationHandling()
ObjectCreationHandling(System.Nullable`1<System.Text.Json.Serialization.JsonObjectCreationHandling>)
EffectiveObjectCreationHandling()
MemberName()
MemberType()
IsVirtual()
IsGetNullable()
IsGetNullable(System.Boolean)
IsSetNullable()
IsSetNullable(System.Boolean)
IsExtensionData()
IsExtensionData(System.Boolean)
IsRequired()
IsRequired(System.Boolean)
AssociatedParameter()
.ctor(System.Type,System.Type,System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Text.Json.JsonSerializerOptions)
GetPropertyPlaceholder()
DeclaringType()
PropertyType()
VerifyMutable()
IsConfigured()
Configure()
ValidateAndCachePropertyName()
DetermineIgnoreCondition()
DetermineSerializationCapabilities()
DetermineNumberHandlingForTypeInfo()
DetermineNumberHandlingForProperty()
DetermineEffectiveObjectCreationHandlingForProperty()
NumberHandingIsApplicable()
HasGetter()
HasSetter()
IgnoreNullTokensOnRead()
IgnoreDefaultValuesOnWrite()
IgnoreReadOnlyMember()
IsForTypeInfo()
Name()
Name(System.String)
NameAsUtf8Bytes()
EscapedNameSection()
Options()
Order()
Order(System.Int32)
ReadJsonAndAddExtensionProperty(System.Object,System.Text.Json.ReadStack&,System.Text.Json.Utf8JsonReader&)
GetDictionaryValueConverter()
AddProperty(System.Text.Json.ReadStackFrame&,System.Collections.Generic.IDictionary`2<System.String,TValue>,TValue)
ReadJsonExtensionDataValue(System.Text.Json.ReadStack&,System.Text.Json.Utf8JsonReader&,System.Object&)
EnsureChildOf(System.Text.Json.Serialization.Metadata.JsonTypeInfo)
TryGetPrePopulatedValue(System.Text.Json.ReadStack&)
JsonTypeInfo()
JsonTypeInfo(System.Text.Json.Serialization.Metadata.JsonTypeInfo)
IsPropertyTypeInfoConfigured()
IsIgnored()
CanSerialize()
CanDeserialize()
CanDeserializeOrPopulate()
SrcGen_HasJsonInclude()
SrcGen_IsPublic()
NumberHandling()
NumberHandling(System.Nullable`1<System.Text.Json.Serialization.JsonNumberHandling>)
EffectiveNumberHandling()
PropertyIndex()
PropertyIndex(System.Int32)
IsOverriddenOrShadowedBy(System.Text.Json.Serialization.Metadata.JsonPropertyInfo)
DebuggerDisplay()