public void InitializeRoot(Type type, JsonSerializerOptions options) { JsonClassInfo jsonClassInfo = options.GetOrAddClass(type); Debug.Assert(jsonClassInfo.ClassType != ClassType.Invalid); Current.JsonClassInfo = jsonClassInfo; // The initial JsonPropertyInfo will be used to obtain the converter. Current.JsonPropertyInfo = jsonClassInfo.PolicyProperty !; if (options.ReferenceHandling.ShouldReadPreservedReferences()) { ReferenceResolver = new DefaultReferenceResolver(writing: false); } }
public void Initialize(Type type, JsonSerializerOptions options, bool supportContinuation) { JsonClassInfo jsonClassInfo = options.GetOrAddClass(type); Current.JsonClassInfo = jsonClassInfo; // The initial JsonPropertyInfo will be used to obtain the converter. Current.JsonPropertyInfo = jsonClassInfo.PropertyInfoForClassInfo; if (options.ReferenceHandling.ShouldReadPreservedReferences()) { ReferenceResolver = new DefaultReferenceResolver(writing: false); } SupportContinuation = supportContinuation; }
/// <summary> /// Initialize the state without delayed initialization of the JsonClassInfo. /// </summary> public void Initialize(Type type, JsonSerializerOptions options, bool supportContinuation) { JsonClassInfo jsonClassInfo = options.GetOrAddClass(type); Current.JsonClassInfo = jsonClassInfo; if ((jsonClassInfo.ClassType & (ClassType.Enumerable | ClassType.Dictionary)) == 0) { Current.DeclaredJsonPropertyInfo = jsonClassInfo.PropertyInfoForClassInfo; } if (options.ReferenceHandling.ShouldWritePreservedReferences()) { ReferenceResolver = new DefaultReferenceResolver(writing: true); } SupportContinuation = supportContinuation; }
public void Initialize(Type type, JsonSerializerOptions options, bool supportContinuation) { JsonClassInfo jsonClassInfo = options.GetOrAddClass(type); Current.JsonClassInfo = jsonClassInfo; // The initial JsonPropertyInfo will be used to obtain the converter. Current.JsonPropertyInfo = jsonClassInfo.PropertyInfoForClassInfo; bool preserveReferences = options.ReferenceHandler != null; if (preserveReferences) { ReferenceResolver = options.ReferenceHandler !.CreateResolver(writing: false); } SupportContinuation = supportContinuation; UseFastPath = !supportContinuation && !preserveReferences; }
public void Initialize(Type type, JsonSerializerOptions options) { JsonClassInfo = options.GetOrAddClass(type); if (JsonClassInfo.ClassType == ClassType.Value || JsonClassInfo.ClassType == ClassType.Enumerable || JsonClassInfo.ClassType == ClassType.Dictionary) { JsonPropertyInfo = JsonClassInfo.GetPolicyProperty(); } else if (JsonClassInfo.ClassType == ClassType.IDictionaryConstructible) { JsonPropertyInfo = JsonClassInfo.GetPolicyProperty(); IsIDictionaryConstructible = true; } else if (JsonClassInfo.ClassType == ClassType.KeyValuePair) { JsonPropertyInfo = JsonClassInfo.GetPolicyPropertyOfKeyValuePair(); // Advance to the next property, since the first one is the KeyValuePair type itself, // not its first property (Key or Value). PropertyIndex++; } }
/// <summary> /// Initialize the state without delayed initialization of the JsonClassInfo. /// </summary> public void Initialize(Type type, JsonSerializerOptions options, bool supportContinuation) { JsonClassInfo jsonClassInfo = options.GetOrAddClass(type); Current.JsonClassInfo = jsonClassInfo; if ((jsonClassInfo.ClassType & (ClassType.Enumerable | ClassType.Dictionary)) == 0) { Current.DeclaredJsonPropertyInfo = jsonClassInfo.PropertyInfoForClassInfo; } bool preserveReferences = options.ReferenceHandler != null; if (preserveReferences) { ReferenceResolver = options.ReferenceHandler !.CreateResolver(writing: true); } SupportContinuation = supportContinuation; }
public void Initialize(Type type, JsonSerializerOptions options) { JsonClassInfo = options.GetOrAddClass(type); InitializeJsonPropertyInfo(); }
private static void HandleStartDictionary(JsonSerializerOptions options, ref Utf8JsonReader reader, ref ReadStack state) { Debug.Assert(!state.Current.IsProcessingEnumerable); JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; if (jsonPropertyInfo == null) { jsonPropertyInfo = state.Current.JsonClassInfo.CreateRootObject(options); } Debug.Assert(jsonPropertyInfo != null); // A nested object or dictionary so push new frame. if (state.Current.PropertyInitialized) { state.Push(); state.Current.JsonClassInfo = jsonPropertyInfo.ElementClassInfo; state.Current.InitializeJsonPropertyInfo(); state.Current.PropertyInitialized = true; ClassType classType = state.Current.JsonClassInfo.ClassType; if (classType == ClassType.Value && jsonPropertyInfo.ElementClassInfo.Type != typeof(object) && jsonPropertyInfo.ElementClassInfo.Type != typeof(JsonElement)) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(state.Current.JsonClassInfo.Type, reader, state.JsonPath); } JsonClassInfo classInfo = state.Current.JsonClassInfo; if (state.Current.IsProcessingIDictionaryConstructibleOrKeyValuePair) { state.Current.TempDictionaryValues = (IDictionary)classInfo.CreateObject(); } else { if (classInfo.CreateObject == null) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(classInfo.Type, reader, state.JsonPath); return; } state.Current.ReturnValue = classInfo.CreateObject(); } return; } state.Current.PropertyInitialized = true; if (state.Current.IsProcessingIDictionaryConstructibleOrKeyValuePair) { JsonClassInfo dictionaryClassInfo = options.GetOrAddClass(jsonPropertyInfo.RuntimePropertyType); state.Current.TempDictionaryValues = (IDictionary)dictionaryClassInfo.CreateObject(); } // Else if current property is already set (from a constructor, for example), leave as-is. else if (jsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue) == null) { // Create the dictionary. JsonClassInfo dictionaryClassInfo = jsonPropertyInfo.RuntimeClassInfo; IDictionary value = (IDictionary)dictionaryClassInfo.CreateObject(); if (value != null) { if (state.Current.ReturnValue != null) { state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value); } else { // A dictionary is being returned directly, or a nested dictionary. state.Current.SetReturnValue(value); } } } }
private static void HandleStartDictionary(JsonSerializerOptions options, ref ReadStack state) { Debug.Assert(!state.Current.IsProcessingEnumerable()); JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; if (jsonPropertyInfo == null) { jsonPropertyInfo = state.Current.JsonClassInfo.CreateRootObject(options); } Debug.Assert(jsonPropertyInfo != null); // A nested object or dictionary so push new frame. if (state.Current.CollectionPropertyInitialized) { state.Push(); state.Current.JsonClassInfo = jsonPropertyInfo.ElementClassInfo; state.Current.InitializeJsonPropertyInfo(); state.Current.CollectionPropertyInitialized = true; ClassType classType = state.Current.JsonClassInfo.ClassType; if (classType == ClassType.Value) { Type elementClassInfoType = jsonPropertyInfo.ElementClassInfo.Type; if (elementClassInfoType != typeof(object) && elementClassInfoType != typeof(JsonElement)) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(state.Current.JsonClassInfo.Type); } } JsonClassInfo classInfo = state.Current.JsonClassInfo; if (state.Current.IsProcessingIDictionaryConstructible()) { state.Current.TempDictionaryValues = (IDictionary)classInfo.CreateConcreteDictionary(); } else { if (classInfo.CreateObject == null) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(classInfo.Type); return; } state.Current.ReturnValue = classInfo.CreateObject(); } return; } state.Current.CollectionPropertyInitialized = true; if (state.Current.IsProcessingIDictionaryConstructible()) { JsonClassInfo dictionaryClassInfo; if (jsonPropertyInfo.DeclaredPropertyType == jsonPropertyInfo.ImplementedPropertyType) { dictionaryClassInfo = options.GetOrAddClass(jsonPropertyInfo.RuntimePropertyType); } else { dictionaryClassInfo = options.GetOrAddClass(jsonPropertyInfo.DeclaredPropertyType); } state.Current.TempDictionaryValues = (IDictionary)dictionaryClassInfo.CreateConcreteDictionary(); } else { // Create the dictionary. JsonClassInfo dictionaryClassInfo = jsonPropertyInfo.RuntimeClassInfo; IDictionary value = (IDictionary)dictionaryClassInfo.CreateObject(); if (value != null) { if (state.Current.ReturnValue != null) { state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value); } else { // A dictionary is being returned directly, or a nested dictionary. state.Current.SetReturnValue(value); } } } }
internal JsonClassInfo(Type type, JsonSerializerOptions options) { Type = type; Options = options; ClassType = GetClassType(type, options); CreateObject = options.MemberAccessorStrategy.CreateConstructor(type); // Ignore properties on enumerable. switch (ClassType) { case ClassType.Object: { PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Dictionary <string, JsonPropertyInfo> cache = CreatePropertyCache(properties.Length); foreach (PropertyInfo propertyInfo in properties) { // Ignore indexers if (propertyInfo.GetIndexParameters().Length > 0) { continue; } // For now we only support public getters\setters if (propertyInfo.GetMethod?.IsPublic == true || propertyInfo.SetMethod?.IsPublic == true) { JsonPropertyInfo jsonPropertyInfo = AddProperty(propertyInfo.PropertyType, propertyInfo, type, options); Debug.Assert(jsonPropertyInfo != null); // If the JsonPropertyNameAttribute or naming policy results in collisions, throw an exception. if (!JsonHelpers.TryAdd(cache, jsonPropertyInfo.NameAsString, jsonPropertyInfo)) { JsonPropertyInfo other = cache[jsonPropertyInfo.NameAsString]; if (other.ShouldDeserialize == false && other.ShouldSerialize == false) { // Overwrite the one just added since it has [JsonIgnore]. cache[jsonPropertyInfo.NameAsString] = jsonPropertyInfo; } else if (jsonPropertyInfo.ShouldDeserialize == true || jsonPropertyInfo.ShouldSerialize == true) { ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameConflict(this, jsonPropertyInfo); } // else ignore jsonPropertyInfo since it has [JsonIgnore]. } } } if (DetermineExtensionDataProperty(cache)) { // Remove from cache since it is handled independently. cache.Remove(DataExtensionProperty.NameAsString); } // Set as a unit to avoid concurrency issues. PropertyCache = cache; } break; case ClassType.Enumerable: case ClassType.Dictionary: { // Add a single property that maps to the class type so we can have policies applied. AddPolicyProperty(type, options); Type objectType; if (IsNativelySupportedCollection(type)) { // Use the type from the property policy to get any late-bound concrete types (from an interface like IDictionary). objectType = PolicyProperty.RuntimePropertyType; } else { // We need to create the declared instance for types implementing natively supported collections. objectType = PolicyProperty.DeclaredPropertyType; } CreateObject = options.MemberAccessorStrategy.CreateConstructor(objectType); // Create a ClassInfo that maps to the element type which is used for (de)serialization and policies. Type elementType = GetElementType(type, parentType: null, memberInfo: null, options: options); ElementClassInfo = options.GetOrAddClass(elementType); } break; case ClassType.IDictionaryConstructible: { // Add a single property that maps to the class type so we can have policies applied. AddPolicyProperty(type, options); Type elementType = GetElementType(type, parentType: null, memberInfo: null, options: options); CreateConcreteDictionary = options.MemberAccessorStrategy.CreateConstructor( typeof(Dictionary <,>).MakeGenericType(typeof(string), elementType)); CreateObject = options.MemberAccessorStrategy.CreateConstructor(PolicyProperty.DeclaredPropertyType); // Create a ClassInfo that maps to the element type which is used for (de)serialization and policies. ElementClassInfo = options.GetOrAddClass(elementType); } break; case ClassType.Value: // Add a single property that maps to the class type so we can have policies applied. AddPolicyProperty(type, options); break; case ClassType.Unknown: // Add a single property that maps to the class type so we can have policies applied. AddPolicyProperty(type, options); PropertyCache = new Dictionary <string, JsonPropertyInfo>(); break; default: Debug.Fail($"Unexpected class type: {ClassType}"); break; } }
internal JsonClassInfo(Type type, JsonSerializerOptions options) { Type = type; ClassType = GetClassType(type, options); CreateObject = options.ClassMaterializerStrategy.CreateConstructor(type); // Ignore properties on enumerable. switch (ClassType) { case ClassType.Object: { var propertyNames = new HashSet <string>(StringComparer.Ordinal); foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { // Ignore indexers if (propertyInfo.GetIndexParameters().Length > 0) { continue; } // For now we only support public getters\setters if (propertyInfo.GetMethod?.IsPublic == true || propertyInfo.SetMethod?.IsPublic == true) { JsonPropertyInfo jsonPropertyInfo = AddProperty(propertyInfo.PropertyType, propertyInfo, type, options); Debug.Assert(jsonPropertyInfo.NameUsedToCompareAsString != null); // If the JsonPropertyNameAttribute or naming policy results in collisions, throw an exception. if (!propertyNames.Add(jsonPropertyInfo.NameUsedToCompareAsString)) { ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameConflict(this, jsonPropertyInfo); } jsonPropertyInfo.ClearUnusedValuesAfterAdd(); } } DetermineExtensionDataProperty(); } break; case ClassType.Enumerable: case ClassType.Dictionary: { // Add a single property that maps to the class type so we can have policies applied. JsonPropertyInfo policyProperty = AddPolicyProperty(type, options); // Use the type from the property policy to get any late-bound concrete types (from an interface like IDictionary). CreateObject = options.ClassMaterializerStrategy.CreateConstructor(policyProperty.RuntimePropertyType); // Create a ClassInfo that maps to the element type which is used for (de)serialization and policies. Type elementType = GetElementType(type, parentType: null, memberInfo: null, options: options); ElementClassInfo = options.GetOrAddClass(elementType); } break; case ClassType.IDictionaryConstructible: { // Add a single property that maps to the class type so we can have policies applied. AddPolicyProperty(type, options); Type elementType = GetElementType(type, parentType: null, memberInfo: null, options: options); CreateObject = options.ClassMaterializerStrategy.CreateConstructor( typeof(Dictionary <,>).MakeGenericType(typeof(string), elementType)); // Create a ClassInfo that maps to the element type which is used for (de)serialization and policies. ElementClassInfo = options.GetOrAddClass(elementType); } break; case ClassType.Value: case ClassType.Unknown: // Add a single property that maps to the class type so we can have policies applied. AddPolicyProperty(type, options); break; default: Debug.Fail($"Unexpected class type: {ClassType}"); break; } }
internal JsonClassInfo(Type type, JsonSerializerOptions options) { Type = type; ClassType = GetClassType(type); CreateObject = options.ClassMaterializerStrategy.CreateConstructor(type); // Ignore properties on enumerable. switch (ClassType) { case ClassType.Object: { var propertyNames = new HashSet <string>(StringComparer.Ordinal); foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { // Ignore indexers if (propertyInfo.GetIndexParameters().Length > 0) { continue; } // For now we only support public getters\setters if (propertyInfo.GetMethod?.IsPublic == true || propertyInfo.SetMethod?.IsPublic == true) { JsonPropertyInfo jsonPropertyInfo = AddProperty(propertyInfo.PropertyType, propertyInfo, type, options); Debug.Assert(jsonPropertyInfo.NameUsedToCompareAsString != null); // If the JsonPropertyNameAttribute or naming policy results in collisions, throw an exception. if (!propertyNames.Add(jsonPropertyInfo.NameUsedToCompareAsString)) { ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameConflict(this, jsonPropertyInfo); } jsonPropertyInfo.ClearUnusedValuesAfterAdd(); } } DetermineExtensionDataProperty(); } break; case ClassType.Enumerable: case ClassType.Dictionary: { // Add a single property that maps to the class type so we can have policies applied. JsonPropertyInfo policyProperty = AddPolicyProperty(type, options); // Use the type from the property policy to get any late-bound concrete types (from an interface like IDictionary). CreateObject = options.ClassMaterializerStrategy.CreateConstructor(policyProperty.RuntimePropertyType); // Create a ClassInfo that maps to the element type which is used for (de)serialization and policies. Type elementType = GetElementType(type, parentType: null, memberInfo: null); ElementClassInfo = options.GetOrAddClass(elementType); } break; case ClassType.IDictionaryConstructible: { // Add a single property that maps to the class type so we can have policies applied. AddPolicyProperty(type, options); Type elementType = GetElementType(type, parentType: null, memberInfo: null); CreateObject = options.ClassMaterializerStrategy.CreateConstructor( typeof(Dictionary <,>).MakeGenericType(typeof(string), elementType)); // Create a ClassInfo that maps to the element type which is used for (de)serialization and policies. ElementClassInfo = options.GetOrAddClass(elementType); } break; // TODO: Utilize converter mechanism to handle (de)serialization of KeyValuePair // when it goes through: https://github.com/dotnet/corefx/issues/36639. case ClassType.KeyValuePair: { // For deserialization, we treat it as ClassType.IDictionaryConstructible so we can parse it like a dictionary // before using converter-like logic to create a KeyValuePair instance. // Add a single property that maps to the class type so we can have policies applied. AddPolicyProperty(type, options); Type elementType = GetElementType(type, parentType: null, memberInfo: null); // Make this Dictionary<string, object> to accomodate input of form {"Key": "MyKey", "Value": 1}. CreateObject = options.ClassMaterializerStrategy.CreateConstructor(typeof(Dictionary <string, object>)); // Create a ClassInfo that maps to the element type which is used for deserialization and policies. ElementClassInfo = options.GetOrAddClass(elementType); // For serialization, we treat it like ClassType.Object to utilize the public getters. // Add Key property PropertyInfo propertyInfo = type.GetProperty("Key", BindingFlags.Public | BindingFlags.Instance); JsonPropertyInfo jsonPropertyInfo = AddProperty(propertyInfo.PropertyType, propertyInfo, type, options); Debug.Assert(jsonPropertyInfo.NameUsedToCompareAsString != null); jsonPropertyInfo.ClearUnusedValuesAfterAdd(); // Add Value property. propertyInfo = type.GetProperty("Value", BindingFlags.Public | BindingFlags.Instance); jsonPropertyInfo = AddProperty(propertyInfo.PropertyType, propertyInfo, type, options); Debug.Assert(jsonPropertyInfo.NameUsedToCompareAsString != null); jsonPropertyInfo.ClearUnusedValuesAfterAdd(); } break; case ClassType.Value: case ClassType.Unknown: // Add a single property that maps to the class type so we can have policies applied. AddPolicyProperty(type, options); break; default: Debug.Fail($"Unexpected class type: {ClassType}"); break; } }