JsonPropertyInfo
Provides JSON serialization-related metadata about a property or field.
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace System.Text.Json.Serialization.Metadata
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
[DebuggerDisplay("MemberInfo={MemberInfo}")]
[EditorBrowsable(EditorBrowsableState.Never)]
public abstract class JsonPropertyInfo
{
internal static readonly JsonPropertyInfo s_missingProperty = GetPropertyPlaceholder();
private JsonTypeInfo _runtimeTypeInfo;
internal ConverterStrategy ConverterStrategy;
internal abstract JsonConverter ConverterBase { get; set; }
internal Type DeclaredPropertyType { get; set; }
internal bool HasGetter { get; set; }
internal bool HasSetter { get; set; }
internal bool IgnoreDefaultValuesOnRead { get; set; }
internal bool IgnoreDefaultValuesOnWrite { get; set; }
internal bool IsForTypeInfo { get; set; }
internal string NameAsString { get; set; }
internal byte[] NameAsUtf8Bytes { get; set; }
internal byte[] EscapedNameSection { get; set; }
internal JsonSerializerOptions Options { get; set; }
internal int Order { get; set; }
internal Type DeclaringType { get; set; }
[System.Runtime.CompilerServices.Nullable(2)]
internal MemberInfo MemberInfo { get; set; }
internal JsonTypeInfo RuntimeTypeInfo {
get {
if (_runtimeTypeInfo == null)
_runtimeTypeInfo = Options.GetOrAddClass(RuntimePropertyType);
return _runtimeTypeInfo;
}
set {
_runtimeTypeInfo = value;
}
}
[System.Runtime.CompilerServices.Nullable(2)]
internal Type RuntimePropertyType { get; set; }
internal bool ShouldSerialize { get; set; }
internal bool ShouldDeserialize { get; set; }
internal bool IsIgnored { get; set; }
internal bool SrcGen_HasJsonInclude { get; set; }
internal bool SrcGen_IsExtensionData { get; set; }
internal bool SrcGen_IsPublic { get; set; }
internal JsonNumberHandling? NumberHandling { get; set; }
internal bool PropertyTypeCanBeNull { get; set; }
internal JsonIgnoreCondition? IgnoreCondition { get; set; }
internal MemberTypes MemberType { get; set; }
[System.Runtime.CompilerServices.Nullable(2)]
internal string ClrName { get; set; }
internal bool IsVirtual { get; set; }
[System.Runtime.CompilerServices.Nullable(2)]
internal abstract object DefaultValue { get; }
internal JsonPropertyInfo()
{
}
internal static JsonPropertyInfo GetPropertyPlaceholder()
{
JsonPropertyInfo jsonPropertyInfo = new JsonPropertyInfo<object>();
jsonPropertyInfo.NameAsString = string.Empty;
return jsonPropertyInfo;
}
internal static JsonPropertyInfo CreateIgnoredPropertyPlaceholder(MemberInfo memberInfo, Type memberType, bool isVirtual, JsonSerializerOptions options)
{
JsonPropertyInfo jsonPropertyInfo = new JsonPropertyInfo<sbyte>();
jsonPropertyInfo.Options = options;
jsonPropertyInfo.MemberInfo = memberInfo;
jsonPropertyInfo.IsIgnored = true;
jsonPropertyInfo.DeclaredPropertyType = memberType;
jsonPropertyInfo.IsVirtual = isVirtual;
jsonPropertyInfo.DeterminePropertyName();
return jsonPropertyInfo;
}
internal virtual void GetPolicies(JsonIgnoreCondition? ignoreCondition, JsonNumberHandling? declaringTypeNumberHandling)
{
if (IsForTypeInfo)
DetermineNumberHandlingForTypeInfo(declaringTypeNumberHandling);
else {
DetermineSerializationCapabilities(ignoreCondition);
DeterminePropertyName();
DetermineIgnoreCondition(ignoreCondition);
JsonPropertyOrderAttribute attribute = GetAttribute<JsonPropertyOrderAttribute>(MemberInfo);
if (attribute != null)
Order = attribute.Order;
DetermineNumberHandlingForProperty(GetAttribute<JsonNumberHandlingAttribute>(MemberInfo)?.Handling, declaringTypeNumberHandling);
}
}
private void DeterminePropertyName()
{
ClrName = MemberInfo.Name;
JsonPropertyNameAttribute attribute = GetAttribute<JsonPropertyNameAttribute>(MemberInfo);
if (attribute != null) {
string name = attribute.Name;
if (name == null)
ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameNull(DeclaringType, this);
NameAsString = name;
} else if (Options.PropertyNamingPolicy != null) {
string text = Options.PropertyNamingPolicy.ConvertName(MemberInfo.Name);
if (text == null)
ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameNull(DeclaringType, this);
NameAsString = text;
} else {
NameAsString = MemberInfo.Name;
}
NameAsUtf8Bytes = Encoding.UTF8.GetBytes(NameAsString);
EscapedNameSection = JsonHelpers.GetEscapedPropertyNameSection(NameAsUtf8Bytes, Options.Encoder);
}
internal void DetermineSerializationCapabilities(JsonIgnoreCondition? ignoreCondition)
{
if ((ConverterStrategy & (ConverterStrategy)24) == ConverterStrategy.None) {
bool flag = ignoreCondition.HasValue || ((MemberType == MemberTypes.Property) ? (!Options.IgnoreReadOnlyProperties) : (!Options.IgnoreReadOnlyFields));
ShouldSerialize = (HasGetter && (HasSetter | flag));
ShouldDeserialize = HasSetter;
} else if (HasGetter) {
ShouldSerialize = true;
if (HasSetter)
ShouldDeserialize = true;
}
}
internal void DetermineIgnoreCondition(JsonIgnoreCondition? ignoreCondition)
{
if (ignoreCondition.HasValue) {
JsonIgnoreCondition? nullable = ignoreCondition;
JsonIgnoreCondition jsonIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault;
if ((nullable.GetValueOrDefault() == jsonIgnoreCondition) & nullable.HasValue)
IgnoreDefaultValuesOnWrite = true;
else {
nullable = ignoreCondition;
jsonIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
if ((nullable.GetValueOrDefault() == jsonIgnoreCondition) & nullable.HasValue) {
if (PropertyTypeCanBeNull)
IgnoreDefaultValuesOnWrite = true;
else
ThrowHelper.ThrowInvalidOperationException_IgnoreConditionOnValueTypeInvalid(ClrName, DeclaringType);
}
}
} else if (Options.IgnoreNullValues) {
if (PropertyTypeCanBeNull) {
IgnoreDefaultValuesOnRead = true;
IgnoreDefaultValuesOnWrite = true;
}
} else if (Options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingNull) {
if (PropertyTypeCanBeNull)
IgnoreDefaultValuesOnWrite = true;
} else if (Options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingDefault) {
IgnoreDefaultValuesOnWrite = true;
}
}
internal void DetermineNumberHandlingForTypeInfo(JsonNumberHandling? numberHandling)
{
if (numberHandling.HasValue) {
JsonNumberHandling? nullable = numberHandling;
JsonNumberHandling jsonNumberHandling = JsonNumberHandling.Strict;
if (!((nullable.GetValueOrDefault() == jsonNumberHandling) & nullable.HasValue) && !ConverterBase.IsInternalConverter)
ThrowHelper.ThrowInvalidOperationException_NumberHandlingOnPropertyInvalid(this);
}
if (NumberHandingIsApplicable()) {
NumberHandling = numberHandling;
if (!NumberHandling.HasValue && Options.NumberHandling != 0)
NumberHandling = Options.NumberHandling;
}
}
internal void DetermineNumberHandlingForProperty(JsonNumberHandling? propertyNumberHandling, JsonNumberHandling? declaringTypeNumberHandling)
{
if (NumberHandingIsApplicable()) {
JsonNumberHandling? numberHandling = propertyNumberHandling ?? declaringTypeNumberHandling;
if (!numberHandling.HasValue && Options.NumberHandling != 0)
numberHandling = Options.NumberHandling;
NumberHandling = numberHandling;
} else if (propertyNumberHandling.HasValue) {
JsonNumberHandling? nullable = propertyNumberHandling;
JsonNumberHandling jsonNumberHandling = JsonNumberHandling.Strict;
if (!((nullable.GetValueOrDefault() == jsonNumberHandling) & nullable.HasValue))
ThrowHelper.ThrowInvalidOperationException_NumberHandlingOnPropertyInvalid(this);
}
}
private bool NumberHandingIsApplicable()
{
if (ConverterBase.IsInternalConverterForNumberType)
return true;
Type type = (ConverterBase.IsInternalConverter && ((ConverterStrategy)24 & ConverterStrategy) != 0) ? ConverterBase.ElementType : DeclaredPropertyType;
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 static TAttribute GetAttribute<TAttribute>(MemberInfo memberInfo) where TAttribute : Attribute
{
return (TAttribute)memberInfo.GetCustomAttribute(typeof(TAttribute), false);
}
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 virtual void Initialize(Type parentClassType, Type declaredPropertyType, Type runtimePropertyType, ConverterStrategy runtimeClassType, MemberInfo memberInfo, bool isVirtual, JsonConverter converter, JsonIgnoreCondition? ignoreCondition, JsonNumberHandling? parentTypeNumberHandling, JsonSerializerOptions options)
{
DeclaringType = parentClassType;
DeclaredPropertyType = declaredPropertyType;
RuntimePropertyType = runtimePropertyType;
ConverterStrategy = runtimeClassType;
MemberInfo = memberInfo;
IsVirtual = isVirtual;
ConverterBase = converter;
Options = options;
}
internal abstract void InitializeForTypeInfo(Type declaredType, JsonTypeInfo runtimeTypeInfo, JsonConverter converter, JsonSerializerOptions options);
internal bool ReadJsonAndAddExtensionProperty(object obj, 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 {
JsonConverter<object> jsonConverter = (JsonConverter<object>)<ReadJsonAndAddExtensionProperty>g__GetDictionaryValueConverter|66_0(JsonTypeInfo.ObjectType);
object value = jsonConverter.Read(ref reader, JsonTypeInfo.ObjectType, Options);
dictionary[state.Current.JsonPropertyNameAsString] = value;
}
} else {
IDictionary<string, JsonElement> dictionary2 = valueAsObject as IDictionary<string, JsonElement>;
if (dictionary2 != null) {
Type typeFromHandle = typeof(JsonElement);
JsonConverter<JsonElement> jsonConverter2 = (JsonConverter<JsonElement>)<ReadJsonAndAddExtensionProperty>g__GetDictionaryValueConverter|66_0(typeFromHandle);
JsonElement value2 = jsonConverter2.Read(ref reader, typeFromHandle, Options);
dictionary2[state.Current.JsonPropertyNameAsString] = value2;
} else
ConverterBase.ReadElementAndSetProperty(valueAsObject, state.Current.JsonPropertyNameAsString, ref reader, Options, ref state);
}
return true;
}
internal abstract bool ReadJsonAndSetMember(object obj, ref ReadStack state, ref Utf8JsonReader reader);
internal abstract bool ReadJsonAsObject(ref ReadStack state, ref Utf8JsonReader reader, out object value);
internal bool ReadJsonExtensionDataValue(ref ReadStack state, ref Utf8JsonReader reader, out object value)
{
if (RuntimeTypeInfo.ElementType == JsonTypeInfo.ObjectType && reader.TokenType == JsonTokenType.Null) {
value = null;
return true;
}
JsonConverter<JsonElement> jsonConverter = (JsonConverter<JsonElement>)Options.GetConverterInternal(typeof(JsonElement));
if (!jsonConverter.TryRead(ref reader, typeof(JsonElement), Options, ref state, out JsonElement value2)) {
value = null;
return false;
}
value = value2;
return true;
}
internal abstract void SetExtensionDictionaryAsObject(object obj, object extensionDict);
}
}