<PackageReference Include="System.Text.Json" Version="9.0.5" />

JsonPropertyInfo<T>

using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; namespace System.Text.Json.Serialization.Metadata { internal sealed class JsonPropertyInfo<T> : JsonPropertyInfo { private Func<object, T> _typedGet; private Action<object, T> _typedSet; private Func<object, T, bool> _shouldSerializeTyped; private JsonConverter<T> _typedEffectiveConverter; internal new Func<object, T> Get { get { return _typedGet; } set { SetGetter(value); } } internal new Action<object, T> Set { get { return _typedSet; } set { SetSetter(value); } } internal new Func<object, T, bool> ShouldSerialize { get { return _shouldSerializeTyped; } set { SetShouldSerialize(value); } } internal override object DefaultValue => default(T); internal override bool PropertyTypeCanBeNull => default(T) == null; internal new JsonConverter<T> EffectiveConverter => _typedEffectiveConverter; internal JsonPropertyInfo(Type declaringType, JsonTypeInfo declaringTypeInfo, JsonSerializerOptions options) : base(declaringType, typeof(T), declaringTypeInfo, options) { } private protected override void SetGetter(Delegate getter) { if ((object)getter == null) { _typedGet = null; _untypedGet = null; } else { Func<object, T> typedGetter = getter as Func<object, T>; if (typedGetter != null) { _typedGet = typedGetter; Func<object, object> func = getter as Func<object, object>; _untypedGet = ((func != null) ? func : ((Func<object, object>)((object obj) => typedGetter(obj)))); } else { Func<object, object> untypedGet = (Func<object, object>)getter; _typedGet = ((object obj) => (T)untypedGet(obj)); _untypedGet = untypedGet; } } } private protected override void SetSetter(Delegate setter) { if ((object)setter == null) { _typedSet = null; _untypedSet = null; } else { Action<object, T> typedSetter = setter as Action<object, T>; if (typedSetter != null) { _typedSet = typedSetter; Action<object, object> action = setter as Action<object, object>; _untypedSet = ((action != null) ? action : ((Action<object, object>)delegate(object obj, object value) { typedSetter(obj, (T)value); })); } else { Action<object, object> untypedSet = (Action<object, object>)setter; _typedSet = delegate(object obj, T value) { untypedSet(obj, value); }; _untypedSet = untypedSet; } } } private protected override void SetShouldSerialize(Delegate predicate) { if ((object)predicate == null) { _shouldSerializeTyped = null; _shouldSerialize = null; } else { Func<object, T, bool> typedPredicate = predicate as Func<object, T, bool>; if (typedPredicate != null) { _shouldSerializeTyped = typedPredicate; Func<object, object, bool> func = typedPredicate as Func<object, object, bool>; _shouldSerialize = ((func != null) ? func : ((Func<object, object, bool>)((object obj, object value) => typedPredicate(obj, (T)value)))); } else { Func<object, object, bool> untypedPredicate = (Func<object, object, bool>)predicate; _shouldSerializeTyped = ((object obj, T value) => untypedPredicate(obj, value)); _shouldSerialize = untypedPredicate; } } } internal override void AddJsonParameterInfo(JsonParameterInfoValues parameterInfoValues) { base.AssociatedParameter = new JsonParameterInfo<T>(parameterInfoValues, this); _isSetNullable = parameterInfoValues.IsNullable; if (base.Options.RespectRequiredConstructorParameters) _isRequired |= base.AssociatedParameter.IsRequiredParameter; } [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 override void DetermineReflectionPropertyAccessors(MemberInfo memberInfo, bool useNonPublicAccessors) { DefaultJsonTypeInfoResolver.DeterminePropertyAccessors<T>(this, memberInfo, useNonPublicAccessors); } private protected override void DetermineEffectiveConverter(JsonTypeInfo jsonTypeInfo) { _typedEffectiveConverter = (JsonConverter<T>)(_effectiveConverter = (base.Options.ExpandConverterFactory(base.CustomConverter, base.PropertyType)?.CreateCastingConverter<T>() ?? ((JsonTypeInfo<T>)jsonTypeInfo).EffectiveConverter)); } internal override object GetValueAsObject(object obj) { if (base.IsForTypeInfo) return obj; return Get(obj); } internal override bool GetMemberAndWriteJson(object obj, ref WriteStack state, Utf8JsonWriter writer) { T value = Get(obj); if (!EffectiveConverter.IsValueType && base.Options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.IgnoreCycles && value != null && !state.IsContinuation && EffectiveConverter.ConverterStrategy != ConverterStrategy.Value && state.ReferenceResolver.ContainsReferenceForCycleDetection(value)) value = default(T); if (base.IgnoreDefaultValuesOnWrite) { if (IsDefaultValue(value)) return true; } else { Func<object, T, bool> shouldSerialize = ShouldSerialize; if (shouldSerialize != null && !shouldSerialize(obj, value)) return true; } if (value == null) { if (!base.IsGetNullable && base.Options.RespectNullableAnnotations) ThrowHelper.ThrowJsonException_PropertyGetterDisallowNull(base.Name, state.Current.JsonTypeInfo.Type); if (EffectiveConverter.HandleNullOnWrite) { if ((int)state.Current.PropertyState < 2) { state.Current.PropertyState = StackFramePropertyState.Name; writer.WritePropertyNameSection(base.EscapedNameSection); } int currentDepth = writer.CurrentDepth; EffectiveConverter.Write(writer, value, base.Options); if (currentDepth != writer.CurrentDepth) ThrowHelper.ThrowJsonException_SerializationConverterWrite(EffectiveConverter); } else writer.WriteNullSection(base.EscapedNameSection); return true; } if ((int)state.Current.PropertyState < 2) { state.Current.PropertyState = StackFramePropertyState.Name; writer.WritePropertyNameSection(base.EscapedNameSection); } return EffectiveConverter.TryWrite(writer, ref value, base.Options, ref state); } internal override bool GetMemberAndWriteJsonExtensionData(object obj, ref WriteStack state, Utf8JsonWriter writer) { T val = Get(obj); Func<object, T, bool> shouldSerialize = ShouldSerialize; if (shouldSerialize != null && !shouldSerialize(obj, val)) return true; if (val != null) return EffectiveConverter.TryWriteDataExtensionProperty(writer, val, base.Options, ref state); return true; } internal override bool ReadJsonAndSetMember(object obj, [System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, ref Utf8JsonReader reader) { bool flag = reader.TokenType == JsonTokenType.Null; bool flag2; if (flag && !EffectiveConverter.HandleNullOnRead && !state.IsContinuation) { if (default(T) != null || !base.CanDeserialize) { if (default(T) == null) ThrowHelper.ThrowInvalidOperationException_DeserializeUnableToAssignNull(EffectiveConverter.Type); ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(EffectiveConverter.Type); } if (!base.IgnoreNullTokensOnRead) { if (!base.IsSetNullable && base.Options.RespectNullableAnnotations) ThrowHelper.ThrowJsonException_PropertySetterDisallowNull(base.Name, state.Current.JsonTypeInfo.Type); Set(obj, default(T)); } flag2 = true; state.Current.MarkRequiredPropertyAsRead(this); } else if (EffectiveConverter.CanUseDirectReadOrWrite && !state.Current.NumberHandling.HasValue) { if (!flag || !base.IgnoreNullTokensOnRead || default(T) != null) { T val = EffectiveConverter.Read(ref reader, base.PropertyType, base.Options); if (val == null && !base.IsSetNullable && base.Options.RespectNullableAnnotations) ThrowHelper.ThrowJsonException_PropertySetterDisallowNull(base.Name, state.Current.JsonTypeInfo.Type); Set(obj, val); } flag2 = true; state.Current.MarkRequiredPropertyAsRead(this); } else { flag2 = true; if (!flag || !base.IgnoreNullTokensOnRead || default(T) != null || state.IsContinuation) { state.Current.ReturnValue = obj; flag2 = EffectiveConverter.TryRead(ref reader, base.PropertyType, base.Options, ref state, out T value, out bool isPopulatedValue); if (flag2) { if ((typeof(T).IsValueType || !isPopulatedValue) && base.CanDeserialize) { if (value == null && !base.IsSetNullable && base.Options.RespectNullableAnnotations) ThrowHelper.ThrowJsonException_PropertySetterDisallowNull(base.Name, state.Current.JsonTypeInfo.Type); Set(obj, value); } state.Current.MarkRequiredPropertyAsRead(this); } } } return flag2; } internal override bool ReadJsonAsObject([System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, ref Utf8JsonReader reader, out object value) { bool result; if (reader.TokenType == JsonTokenType.Null && !EffectiveConverter.HandleNullOnRead && !state.IsContinuation) { if (default(T) != null) ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(EffectiveConverter.Type); value = default(T); result = true; } else if (EffectiveConverter.CanUseDirectReadOrWrite && !state.Current.NumberHandling.HasValue) { value = EffectiveConverter.Read(ref reader, base.PropertyType, base.Options); result = true; } else { result = EffectiveConverter.TryRead(ref reader, base.PropertyType, base.Options, ref state, out T value2, out bool _); value = value2; } return result; } private protected override void ConfigureIgnoreCondition(JsonIgnoreCondition? ignoreCondition) { if (ignoreCondition.HasValue) { switch (ignoreCondition.GetValueOrDefault()) { case JsonIgnoreCondition.Never: ShouldSerialize = ((object _, T value) => true); break; case JsonIgnoreCondition.Always: ShouldSerialize = ((object _, T value) => false); break; case JsonIgnoreCondition.WhenWritingNull: if (PropertyTypeCanBeNull) { ShouldSerialize = delegate(object _, T value) { if (default(T) != null) return !EqualityComparer<T>.Default.Equals(default(T), value); return value != null; }; base.IgnoreDefaultValuesOnWrite = true; } else ThrowHelper.ThrowInvalidOperationException_IgnoreConditionOnValueTypeInvalid(base.MemberName, base.DeclaringType); break; case JsonIgnoreCondition.WhenWritingDefault: ShouldSerialize = delegate(object _, T value) { if (default(T) != null) return !EqualityComparer<T>.Default.Equals(default(T), value); return value != null; }; base.IgnoreDefaultValuesOnWrite = true; break; } } } private static bool IsDefaultValue(T value) { if (default(T) != null) return EqualityComparer<T>.Default.Equals(default(T), value); return value == null; } } }