コード例 #1
0
        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);
            }
        }
コード例 #2
0
        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;
        }
コード例 #3
0
        internal JsonPropertyInfo GetJsonPropertyInfoFromClassInfo(JsonClassInfo classInfo, JsonSerializerOptions options)
        {
            if (classInfo.ClassType != ClassType.Object)
            {
                return(classInfo.GetPolicyProperty());
            }

            Type objectType = classInfo.Type;

            if (!_objectJsonProperties.TryGetValue(objectType, out JsonPropertyInfo propertyInfo))
            {
                propertyInfo = JsonClassInfo.CreateProperty(objectType, objectType, null, typeof(object), options);
                _objectJsonProperties[objectType] = propertyInfo;
            }

            return(propertyInfo);
        }
コード例 #4
0
ファイル: JsonPropertyInfo.cs プロジェクト: tmds/corefx
        public virtual void Initialize(
            Type parentClassType,
            Type declaredPropertyType,
            Type runtimePropertyType,
            Type implementedPropertyType,
            PropertyInfo propertyInfo,
            Type elementType,
            JsonConverter converter,
            JsonSerializerOptions options)
        {
            ParentClassType         = parentClassType;
            DeclaredPropertyType    = declaredPropertyType;
            RuntimePropertyType     = runtimePropertyType;
            ImplementedPropertyType = implementedPropertyType;
            PropertyInfo            = propertyInfo;
            ElementType             = elementType;
            Options        = options;
            IsNullableType = runtimePropertyType.IsGenericType && runtimePropertyType.GetGenericTypeDefinition() == typeof(Nullable <>);
            CanBeNull      = IsNullableType || !runtimePropertyType.IsValueType;

            if (converter != null)
            {
                ConverterBase = converter;

                HasInternalConverter = (converter.GetType().Assembly == GetType().Assembly);

                // Avoid calling GetClassType since it will re-ask if there is a converter which is slow.
                if (runtimePropertyType == typeof(object))
                {
                    ClassType = ClassType.Unknown;
                }
                else
                {
                    ClassType = ClassType.Value;
                }
            }
            // Special case for immutable collections.
            else if (declaredPropertyType != implementedPropertyType && !JsonClassInfo.IsNativelySupportedCollection(declaredPropertyType))
            {
                ClassType = JsonClassInfo.GetClassType(declaredPropertyType, options);
            }
            else
            {
                ClassType = JsonClassInfo.GetClassType(runtimePropertyType, options);
            }
        }
コード例 #5
0
        /// <summary>
        /// Initialize the state without delayed initialization of the JsonClassInfo.
        /// </summary>
        public JsonConverter Initialize(Type type, JsonSerializerOptions options, bool supportContinuation)
        {
            JsonClassInfo jsonClassInfo = options.GetOrAddClassForRootType(type);

            Current.JsonClassInfo            = jsonClassInfo;
            Current.DeclaredJsonPropertyInfo = jsonClassInfo.PropertyInfoForClassInfo;
            Current.NumberHandling           = Current.DeclaredJsonPropertyInfo.NumberHandling;

            if (options.ReferenceHandler != null)
            {
                ReferenceResolver = options.ReferenceHandler !.CreateResolver(writing: true);
            }

            SupportContinuation = supportContinuation;

            return(jsonClassInfo.PropertyInfoForClassInfo.ConverterBase);
        }
コード例 #6
0
ファイル: JsonPropertyInfo.cs プロジェクト: jkotalik/corefx
        private void DeterminePropertyName()
        {
            if (PropertyInfo == null)
            {
                return;
            }

            JsonPropertyNameAttribute nameAttribute = GetAttribute <JsonPropertyNameAttribute>(PropertyInfo);

            if (nameAttribute != null)
            {
                string name = nameAttribute.Name;
                if (name == null)
                {
                    ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameNull(ParentClassType, this);
                }

                NameAsString = name;
            }
            else if (Options.PropertyNamingPolicy != null)
            {
                string name = Options.PropertyNamingPolicy.ConvertName(PropertyInfo.Name);
                if (name == null)
                {
                    ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameNull(ParentClassType, this);
                }

                NameAsString = name;
            }
            else
            {
                NameAsString = PropertyInfo.Name;
            }

            Debug.Assert(NameAsString != null);

            // At this point propertyName is valid UTF16, so just call the simple UTF16->UTF8 encoder.
            Name = Encoding.UTF8.GetBytes(NameAsString);

            // Cache the escaped property name.
            EscapedName = JsonEncodedText.Encode(Name, Options.Encoder);

            ulong key = JsonClassInfo.GetKey(Name);

            PropertyNameKey = key;
        }
コード例 #7
0
        public static object CreateEnumerableValue(ref ReadStack state)
        {
            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo;

            // If the property has an EnumerableConverter, then we use tempEnumerableValues.
            if (jsonPropertyInfo.EnumerableConverter != null)
            {
                IList         converterList;
                JsonClassInfo elementClassInfo = jsonPropertyInfo.ElementClassInfo;
                if (elementClassInfo.ClassType == ClassType.Value)
                {
                    converterList = elementClassInfo.PolicyProperty.CreateConverterList();
                }
                else
                {
                    converterList = new List <object>();
                }

                state.Current.TempEnumerableValues = converterList;

                // Clear the value if present to ensure we don't confuse tempEnumerableValues with the collection.
                if (!jsonPropertyInfo.IsPropertyPolicy &&
                    !state.Current.JsonPropertyInfo.IsImmutableArray)
                {
                    jsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, null);
                }

                return(null);
            }

            JsonClassInfo runtimeClassInfo = jsonPropertyInfo.RuntimeClassInfo;

            if (runtimeClassInfo.CreateObject != null)
            {
                return(runtimeClassInfo.CreateObject());
            }
            else
            {
                // Could not create an instance to be returned. For derived types, this means there is no parameterless ctor.
                throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection(
                          jsonPropertyInfo.DeclaredPropertyType,
                          jsonPropertyInfo.ParentClassType,
                          jsonPropertyInfo.PropertyInfo);
            }
        }
コード例 #8
0
        public void Push()
        {
            if (_continuationCount == 0)
            {
                if (_count == 0)
                {
                    // The first stack frame is held in Current.
                    _count = 1;
                }
                else
                {
                    JsonClassInfo      jsonClassInfo  = Current.GetPolymorphicJsonPropertyInfo().RuntimeClassInfo;
                    JsonNumberHandling?numberHandling = Current.NumberHandling;

                    AddCurrent();
                    Current.Reset();

                    Current.JsonClassInfo            = jsonClassInfo;
                    Current.DeclaredJsonPropertyInfo = jsonClassInfo.PropertyInfoForClassInfo;
                    // Allow number handling on property to win over handling on type.
                    Current.NumberHandling = numberHandling ?? Current.DeclaredJsonPropertyInfo.NumberHandling;
                }
            }
            else if (_continuationCount == 1)
            {
                // No need for a push since there is only one stack frame.
                Debug.Assert(_count == 1);
                _continuationCount = 0;
            }
            else
            {
                // A continuation, adjust the index.
                Current = _previous[_count - 1];

                // Check if we are done.
                if (_count == _continuationCount)
                {
                    _continuationCount = 0;
                }
                else
                {
                    _count++;
                }
            }
        }
コード例 #9
0
        /// <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;
        }
コード例 #10
0
ファイル: JsonPropertyInfo.cs プロジェクト: ojhad/corefx
 public virtual void Initialize(
     Type parentClassType,
     Type declaredPropertyType,
     Type runtimePropertyType,
     PropertyInfo propertyInfo,
     Type elementType,
     JsonSerializerOptions options)
 {
     ParentClassType      = parentClassType;
     DeclaredPropertyType = declaredPropertyType;
     RuntimePropertyType  = runtimePropertyType;
     PropertyInfo         = propertyInfo;
     ClassType            = JsonClassInfo.GetClassType(runtimePropertyType);
     _elementType         = elementType;
     Options        = options;
     IsNullableType = runtimePropertyType.IsGenericType && runtimePropertyType.GetGenericTypeDefinition() == typeof(Nullable <>);
     CanBeNull      = IsNullableType || !runtimePropertyType.IsValueType;
 }
コード例 #11
0
        private JsonPropertyInfo AddProperty(Type propertyType, PropertyInfo propertyInfo, Type classType, JsonSerializerOptions options)
        {
            JsonPropertyInfo jsonInfo = CreateProperty(propertyType, propertyType, propertyInfo, classType, options);

            // Convert non-immutable dictionary interfaces to concrete types.
            if (propertyType.IsInterface && jsonInfo.ClassType == ClassType.Dictionary)
            {
                JsonClassInfo    elementClassInfo    = jsonInfo.ElementClassInfo;
                JsonPropertyInfo elementPropertyInfo = options.GetJsonPropertyInfoFromClassInfo(elementClassInfo, options);

                Type newPropertyType = elementPropertyInfo.GetDictionaryConcreteType();
                if (propertyType != newPropertyType)
                {
                    jsonInfo = CreateProperty(propertyType, newPropertyType, propertyInfo, classType, options);
                }
            }
            else if (jsonInfo.ClassType == ClassType.Enumerable &&
                     !propertyType.IsArray &&
                     (IsDeserializedByAssigningFromList(propertyType) || IsSetInterface(propertyType)))
            {
                JsonClassInfo    elementClassInfo    = jsonInfo.ElementClassInfo;
                JsonPropertyInfo elementPropertyInfo = options.GetJsonPropertyInfoFromClassInfo(elementClassInfo, options);

                // Get a runtime type for the property. e.g. ISet<T> -> HashSet<T>, ICollection -> List<object>
                // We use the element's JsonPropertyInfo so we can utilize the generic support.
                Type newPropertyType = elementPropertyInfo.GetConcreteType(propertyType);
                if ((propertyType != newPropertyType) && propertyType.IsAssignableFrom(newPropertyType))
                {
                    jsonInfo = CreateProperty(propertyType, newPropertyType, propertyInfo, classType, options);
                }
            }

            if (propertyInfo != null)
            {
                _propertyRefs.Add(new PropertyRef(GetKey(jsonInfo.NameUsedToCompare), jsonInfo));
            }
            else
            {
                // A single property or an IEnumerable
                _propertyRefs.Add(new PropertyRef(0, jsonInfo));
            }

            return(jsonInfo);
        }
コード例 #12
0
ファイル: WriteStack.cs プロジェクト: pgovind/runtime
        public void Push(JsonClassInfo nextClassInfo, object nextValue)
        {
            Push();
            Current.JsonClassInfo = nextClassInfo;
            Current.CurrentValue  = nextValue;

            ClassType classType = nextClassInfo.ClassType;

            if (classType == ClassType.Enumerable || nextClassInfo.ClassType == ClassType.Dictionary)
            {
                Current.PopStackOnEndCollection = true;
                Current.JsonPropertyInfo        = Current.JsonClassInfo.PolicyProperty;
            }
            else
            {
                Debug.Assert(nextClassInfo.ClassType == ClassType.Object || nextClassInfo.ClassType == ClassType.Unknown);
                Current.PopStackOnEndObject = true;
            }
        }
コード例 #13
0
        public void Initialize(Type type, JsonSerializerOptions options, bool supportContinuation)
        {
            JsonClassInfo jsonClassInfo = options.GetOrAddClassForRootType(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;
        }
コード例 #14
0
        public void Read(JsonTokenType tokenType, ref ReadStack state, ref Utf8JsonReader reader)
        {
            Debug.Assert(ShouldDeserialize);

            JsonPropertyInfo propertyInfo;
            JsonClassInfo    elementClassInfo = ElementClassInfo;

            if (elementClassInfo != null && (propertyInfo = elementClassInfo.PolicyProperty) != null)
            {
                if (!state.Current.CollectionPropertyInitialized)
                {
                    ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(propertyInfo.RuntimePropertyType);
                }

                // Forward the setter to the value-based JsonPropertyInfo.
                propertyInfo.ReadEnumerable(tokenType, ref state, ref reader);
            }
            // For performance on release build, don't verify converter correctness for internal converters.
            else if (HasInternalConverter)
            {
#if DEBUG
                JsonTokenType originalTokenType     = reader.TokenType;
                int           originalDepth         = reader.CurrentDepth;
                long          originalBytesConsumed = reader.BytesConsumed;
#endif

                OnRead(ref state, ref reader);

#if DEBUG
                VerifyRead(originalTokenType, originalDepth, originalBytesConsumed, ref reader);
#endif
            }
            else
            {
                JsonTokenType originalTokenType     = reader.TokenType;
                int           originalDepth         = reader.CurrentDepth;
                long          originalBytesConsumed = reader.BytesConsumed;

                OnRead(ref state, ref reader);

                VerifyRead(originalTokenType, originalDepth, originalBytesConsumed, ref reader);
            }
        }
コード例 #15
0
ファイル: WriteStack.cs プロジェクト: lateralusX/runtime
        public void Push()
        {
            if (_continuationCount == 0)
            {
                if (_count == 0)
                {
                    // The first stack frame is held in Current.
                    _count = 1;
                }
                else
                {
                    JsonClassInfo jsonClassInfo = Current.GetPolymorphicJsonPropertyInfo().RuntimeClassInfo;

                    AddCurrent();
                    Current.Reset();

                    Current.JsonClassInfo            = jsonClassInfo;
                    Current.DeclaredJsonPropertyInfo = jsonClassInfo.PolicyProperty !;
                }
            }
            else if (_continuationCount == 1)
            {
                // No need for a push since there is only one stack frame.
                Debug.Assert(_count == 1);
                _continuationCount = 0;
            }
            else
            {
                // A continuation, adjust the index.
                Current = _previous[_count - 1];

                // Check if we are done.
                if (_count == _continuationCount)
                {
                    _continuationCount = 0;
                }
                else
                {
                    _count++;
                }
            }
        }
コード例 #16
0
        private static void HandleStartObject(JsonSerializerOptions options, ref Utf8JsonReader reader, ref ReadStack state)
        {
            Debug.Assert(!state.Current.IsProcessingDictionary && !state.Current.IsProcessingIDictionaryConstructible);

            if (state.Current.IsProcessingEnumerable)
            {
                // A nested object within an enumerable.
                Type objType = state.Current.GetElementType();
                state.Push();
                state.Current.Initialize(objType, options);
            }
            else if (state.Current.JsonPropertyInfo != null)
            {
                // Nested object.
                Type objType = state.Current.JsonPropertyInfo.RuntimePropertyType;
                state.Push();
                state.Current.Initialize(objType, options);
            }

            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            if (classInfo.CreateObject is null && classInfo.ClassType == ClassType.Object)
            {
                if (classInfo.Type.IsInterface)
                {
                    ThrowHelper.ThrowInvalidOperationException_DeserializePolymorphicInterface(classInfo.Type);
                }
                else
                {
                    ThrowHelper.ThrowInvalidOperationException_DeserializeMissingParameterlessConstructor(classInfo.Type);
                }
            }

            if (state.Current.IsProcessingIDictionaryConstructible)
            {
                state.Current.TempDictionaryValues = (IDictionary)classInfo.CreateConcreteDictionary();
            }
            else
            {
                state.Current.ReturnValue = classInfo.CreateObject();
            }
        }
コード例 #17
0
 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++;
     }
 }
コード例 #18
0
ファイル: WriteStack.cs プロジェクト: vscodewinodws/runtime
        /// <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;
        }
コード例 #19
0
        /// <summary>
        /// Initialize the state without delayed initialization of the JsonClassInfo.
        /// </summary>
        public JsonConverter Initialize(Type type, JsonSerializerOptions options, bool supportContinuation)
        {
            JsonClassInfo jsonClassInfo = options.GetOrAddClassForRootType(type);

            Current.JsonClassInfo = jsonClassInfo;

            if ((jsonClassInfo.ClassType & (ClassType.Enumerable | ClassType.Dictionary)) == 0)
            {
                Current.DeclaredJsonPropertyInfo = jsonClassInfo.PropertyInfoForClassInfo;
            }

            if (options.ReferenceHandler != null)
            {
                ReferenceResolver = options.ReferenceHandler !.CreateResolver(writing: true);
            }

            SupportContinuation = supportContinuation;

            return(jsonClassInfo.PropertyInfoForClassInfo.ConverterBase);
        }
コード例 #20
0
        private static bool WriteObject(
            JsonSerializerOptions options,
            Utf8JsonWriter writer,
            ref WriteStack state)
        {
            // Write the start.
            if (!state.Current.StartObjectWritten)
            {
                state.Current.WriteObjectOrArrayStart(ClassType.Object, writer);
            }

            if (state.Current.MoveToNextProperty)
            {
                state.Current.NextProperty();
            }

            // Determine if we are done enumerating properties.
            // If the ClassType is unknown, there will be a policy property applied. There is probably
            // a better way to identify policy properties- maybe not put them in the normal property bag?
            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            if (classInfo.ClassType != ClassType.Unknown && state.Current.PropertyIndex != classInfo.PropertyCount)
            {
                HandleObject(options, writer, ref state);
                return(false);
            }

            writer.WriteEndObject();

            if (state.Current.PopStackOnEndObject)
            {
                state.Pop();
            }
            else
            {
                state.Current.EndObject();
            }

            return(true);
        }
コード例 #21
0
        private static bool WriteObject(
            JsonSerializerOptions options,
            Utf8JsonWriter writer,
            ref WriteStack state)
        {
            // Write the start.
            if (!state.Current.StartObjectWritten)
            {
                state.Current.WriteObjectOrArrayStart(ClassType.Object, writer);
                state.Current.PropertyEnumerator = state.Current.JsonClassInfo.PropertyCache.GetEnumerator();
                state.Current.NextProperty();
            }
            else if (state.Current.MoveToNextProperty)
            {
                state.Current.NextProperty();
            }

            // Determine if we are done enumerating properties.
            // If the ClassType is unknown, there will be a policy property applied
            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            if (classInfo.ClassType != ClassType.Unknown && state.Current.PropertyEnumeratorActive)
            {
                HandleObject(options, writer, ref state);
                return(false);
            }

            writer.WriteEndObject();

            if (state.Current.PopStackOnEndObject)
            {
                state.Pop();
            }
            else
            {
                state.Current.EndObject();
            }

            return(true);
        }
コード例 #22
0
ファイル: ReadStackFrame.cs プロジェクト: twinkleeee/runtime
        public static object?CreateDictionaryValue(ref ReadStack state)
        {
            Debug.Assert(state.Current.JsonPropertyInfo != null);
            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo;

            // If the property has a DictionaryConverter, then we use tempDictionaryValues.
            if (jsonPropertyInfo.DictionaryConverter != null)
            {
                IDictionary   converterDictionary;
                JsonClassInfo elementClassInfo = jsonPropertyInfo.ElementClassInfo !;
                if (elementClassInfo.ClassType == ClassType.Value)
                {
                    converterDictionary = elementClassInfo.PolicyProperty !.CreateConverterDictionary();
                }
                else
                {
                    converterDictionary = new Dictionary <string, object>();
                }

                state.Current.TempDictionaryValues = converterDictionary;

                // Clear the value if present to ensure we don't confuse TempDictionaryValues with the collection.
                if (!jsonPropertyInfo.IsPropertyPolicy && jsonPropertyInfo.CanBeNull)
                {
                    jsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, null);
                }

                return(null);
            }

            JsonClassInfo runtimeClassInfo = jsonPropertyInfo.RuntimeClassInfo;

            if (runtimeClassInfo.CreateObject == null)
            {
                ThrowHelper.ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(jsonPropertyInfo.DeclaredPropertyType);
            }

            return(runtimeClassInfo.CreateObject());
        }
コード例 #23
0
        public static object CreateEnumerableValue(ref ReadStack state)
        {
            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo;

            // If the property has an EnumerableConverter, then we use tempEnumerableValues.
            if (jsonPropertyInfo.EnumerableConverter != null)
            {
                IList         converterList;
                JsonClassInfo elementClassInfo = jsonPropertyInfo.ElementClassInfo;
                if (elementClassInfo.ClassType == ClassType.Value)
                {
                    converterList = elementClassInfo.PolicyProperty.CreateConverterList();
                }
                else
                {
                    converterList = new List <object>();
                }

                state.Current.TempEnumerableValues = converterList;

                // Clear the value if present to ensure we don't confuse TempEnumerableValues with the collection.
                if (!jsonPropertyInfo.IsPropertyPolicy && jsonPropertyInfo.CanBeNull)
                {
                    jsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, null);
                }

                return(null);
            }

            JsonClassInfo runtimeClassInfo = jsonPropertyInfo.RuntimeClassInfo;

            if (runtimeClassInfo.CreateObject == null)
            {
                ThrowHelper.ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(jsonPropertyInfo.DeclaredPropertyType);
            }

            return(runtimeClassInfo.CreateObject());
        }
コード例 #24
0
ファイル: JsonPropertyInfo.cs プロジェクト: zielmicha/corefx
        public virtual void Initialize(
            Type parentClassType,
            Type declaredPropertyType,
            Type runtimePropertyType,
            PropertyInfo propertyInfo,
            Type elementType,
            JsonConverter converter,
            JsonSerializerOptions options)
        {
            ParentClassType      = parentClassType;
            DeclaredPropertyType = declaredPropertyType;
            RuntimePropertyType  = runtimePropertyType;
            PropertyInfo         = propertyInfo;
            _elementType         = elementType;
            Options        = options;
            IsNullableType = runtimePropertyType.IsGenericType && runtimePropertyType.GetGenericTypeDefinition() == typeof(Nullable <>);
            CanBeNull      = IsNullableType || !runtimePropertyType.IsValueType;

            if (converter != null)
            {
                ConverterBase = converter;

                // Avoid calling GetClassType since it will re-ask if there is a converter which is slow.
                if (runtimePropertyType == typeof(object))
                {
                    ClassType = ClassType.Unknown;
                }
                else
                {
                    ClassType = ClassType.Value;
                }
            }
            else
            {
                ClassType = JsonClassInfo.GetClassType(runtimePropertyType, options);
            }
        }
コード例 #25
0
ファイル: ReadStackFrame.cs プロジェクト: swellhh/corefx
        public static object CreateEnumerableValue(ref Utf8JsonReader reader, ref ReadStack state, JsonSerializerOptions options)
        {
            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo;

            // If the property has an EnumerableConverter, then we use tempEnumerableValues.
            if (jsonPropertyInfo.EnumerableConverter != null)
            {
                IList converterList;
                if (jsonPropertyInfo.ElementClassInfo.ClassType == ClassType.Value)
                {
                    converterList = jsonPropertyInfo.ElementClassInfo.PolicyProperty.CreateConverterList();
                }
                else
                {
                    converterList = new List <object>();
                }

                state.Current.TempEnumerableValues = converterList;

                return(null);
            }

            Type propertyType = state.Current.JsonPropertyInfo.RuntimePropertyType;

            if (typeof(IList).IsAssignableFrom(propertyType))
            {
                // If IList, add the members as we create them.
                JsonClassInfo collectionClassInfo = state.Current.JsonPropertyInfo.RuntimeClassInfo;
                IList         collection          = (IList)collectionClassInfo.CreateObject();
                return(collection);
            }
            else
            {
                ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(propertyType, reader, state.JsonPath);
                return(null);
            }
        }
コード例 #26
0
ファイル: JsonPropertyInfo.cs プロジェクト: jkotalik/corefx
        private void DetermineSerializationCapabilities()
        {
            if (ClassType != ClassType.Enumerable &&
                ClassType != ClassType.Dictionary &&
                ClassType != ClassType.IDictionaryConstructible)
            {
                // We serialize if there is a getter + not ignoring readonly properties.
                ShouldSerialize = HasGetter && (HasSetter || !Options.IgnoreReadOnlyProperties);

                // We deserialize if there is a setter.
                ShouldDeserialize = HasSetter;
            }
            else
            {
                if (HasGetter)
                {
                    ShouldSerialize = true;

                    if (HasSetter)
                    {
                        ShouldDeserialize = true;

                        if (RuntimePropertyType.IsArray)
                        {
                            // Verify that we don't have a multidimensional array.
                            if (RuntimePropertyType.GetArrayRank() > 1)
                            {
                                throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection(RuntimePropertyType, ParentClassType, PropertyInfo);
                            }

                            EnumerableConverter = s_jsonArrayConverter;
                        }
                        else if (ClassType == ClassType.IDictionaryConstructible)
                        {
                            // Natively supported type.
                            if (DeclaredPropertyType == ImplementedPropertyType)
                            {
                                if (RuntimePropertyType.FullName.StartsWith(JsonClassInfo.ImmutableNamespaceName))
                                {
                                    DefaultImmutableDictionaryConverter.RegisterImmutableDictionary(
                                        RuntimePropertyType, JsonClassInfo.GetElementType(RuntimePropertyType, ParentClassType, PropertyInfo, Options), Options);

                                    DictionaryConverter = s_jsonImmutableDictionaryConverter;
                                }
                                else if (JsonClassInfo.IsDeserializedByConstructingWithIDictionary(RuntimePropertyType))
                                {
                                    DictionaryConverter = s_jsonIDictionaryConverter;
                                }
                            }
                            // Type that implements a type with ClassType IDictionaryConstructible.
                            else
                            {
                                DictionaryConverter = s_jsonDerivedDictionaryConverter;
                            }
                        }
                        else if (ClassType == ClassType.Enumerable)
                        {
                            // Else if it's an implementing type whose runtime type is not assignable to IList.
                            if (DeclaredPropertyType != ImplementedPropertyType &&
                                (!typeof(IList).IsAssignableFrom(RuntimePropertyType) ||
                                 ImplementedPropertyType == typeof(ArrayList) ||
                                 ImplementedPropertyType == typeof(IList)))
                            {
                                EnumerableConverter = s_jsonDerivedEnumerableConverter;
                            }
                            else if (JsonClassInfo.IsDeserializedByConstructingWithIList(RuntimePropertyType) ||
                                     (!typeof(IList).IsAssignableFrom(RuntimePropertyType) &&
                                      JsonClassInfo.HasConstructorThatTakesGenericIEnumerable(RuntimePropertyType, Options)))
                            {
                                EnumerableConverter = s_jsonICollectionConverter;
                            }
                            else if (RuntimePropertyType.IsGenericType &&
                                     RuntimePropertyType.FullName.StartsWith(JsonClassInfo.ImmutableNamespaceName) &&
                                     RuntimePropertyType.GetGenericArguments().Length == 1)
                            {
                                DefaultImmutableEnumerableConverter.RegisterImmutableCollection(RuntimePropertyType,
                                                                                                JsonClassInfo.GetElementType(RuntimePropertyType, ParentClassType, PropertyInfo, Options), Options);
                                EnumerableConverter = s_jsonImmutableEnumerableConverter;
                            }
                        }
                    }
                }
            }
        }
コード例 #27
0
        private static bool HandleObject(
            JsonSerializerOptions options,
            Utf8JsonWriter writer,
            ref WriteStack state)
        {
            Debug.Assert(
                state.Current.JsonClassInfo.ClassType == ClassType.Object ||
                state.Current.JsonClassInfo.ClassType == ClassType.Unknown);

            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonClassInfo.GetProperty(state.Current.PropertyIndex);

            if (!jsonPropertyInfo.ShouldSerialize)
            {
                state.Current.MoveToNextProperty = true;
                return(true);
            }

            bool   obtainedValue = false;
            object currentValue  = null;

            // Check for polymorphism.
            if (jsonPropertyInfo.ClassType == ClassType.Unknown)
            {
                currentValue  = jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue);
                obtainedValue = true;
                GetRuntimePropertyInfo(currentValue, state.Current.JsonClassInfo, ref jsonPropertyInfo, options);
            }

            state.Current.JsonPropertyInfo = jsonPropertyInfo;

            if (jsonPropertyInfo.ClassType == ClassType.Value)
            {
                jsonPropertyInfo.Write(ref state, writer);
                state.Current.MoveToNextProperty = true;
                return(true);
            }

            // A property that returns an enumerator keeps the same stack frame.
            if (jsonPropertyInfo.ClassType == ClassType.Enumerable)
            {
                bool endOfEnumerable = HandleEnumerable(jsonPropertyInfo.ElementClassInfo, options, writer, ref state);
                if (endOfEnumerable)
                {
                    state.Current.MoveToNextProperty = true;
                }

                return(endOfEnumerable);
            }

            // A property that returns a dictionary keeps the same stack frame.
            if (jsonPropertyInfo.ClassType == ClassType.Dictionary)
            {
                bool endOfEnumerable = HandleDictionary(jsonPropertyInfo.ElementClassInfo, options, writer, ref state);
                if (endOfEnumerable)
                {
                    state.Current.MoveToNextProperty = true;
                }

                return(endOfEnumerable);
            }

            // A property that returns an immutable dictionary keeps the same stack frame.
            if (jsonPropertyInfo.ClassType == ClassType.IDictionaryConstructible)
            {
                state.Current.IsIDictionaryConstructibleProperty = true;

                bool endOfEnumerable = HandleDictionary(jsonPropertyInfo.ElementClassInfo, options, writer, ref state);
                if (endOfEnumerable)
                {
                    state.Current.MoveToNextProperty = true;
                }

                return(endOfEnumerable);
            }

            // A property that returns an object.
            if (!obtainedValue)
            {
                currentValue = jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue);
            }

            if (currentValue != null)
            {
                // A new stack frame is required.
                JsonPropertyInfo previousPropertyInfo = state.Current.JsonPropertyInfo;
                state.Current.MoveToNextProperty = true;

                JsonClassInfo nextClassInfo = jsonPropertyInfo.RuntimeClassInfo;
                state.Push(nextClassInfo, currentValue);

                // Set the PropertyInfo so we can obtain the property name in order to write it.
                state.Current.JsonPropertyInfo = previousPropertyInfo;
            }
            else
            {
                if (!jsonPropertyInfo.IgnoreNullValues)
                {
                    writer.WriteNull(jsonPropertyInfo.EscapedName.Value);
                }

                state.Current.MoveToNextProperty = true;
            }

            return(true);
        }
コード例 #28
0
        private static bool HandleDictionary(
            JsonClassInfo elementClassInfo,
            JsonSerializerOptions options,
            Utf8JsonWriter writer,
            ref WriteStack state)
        {
            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo !;

            if (state.Current.CollectionEnumerator == null)
            {
                IEnumerable?enumerable = (IEnumerable?)jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue);
                if (enumerable == null)
                {
                    if ((state.Current.JsonClassInfo !.ClassType != ClassType.Object ||        // Write null dictionary values
                         !jsonPropertyInfo.IgnoreNullValues) &&                                // Ignore ClassType.Object properties if IgnoreNullValues is true
                        state.Current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing) // Ignore null extension property (which is a dictionary)
                    {
                        // Write a null object or enumerable.
                        state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer, options, writeNull: true);
                    }

                    if (state.Current.PopStackOnEndCollection)
                    {
                        state.Pop();
                    }

                    return(true);
                }

                if (state.Current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing)
                {
                    if (options.ReferenceHandling.ShouldWritePreservedReferences())
                    {
                        if (WriteReference(ref state, writer, options, ClassType.Dictionary, enumerable))
                        {
                            return(WriteEndDictionary(ref state));
                        }
                    }
                    else
                    {
                        state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer, options);
                    }
                }

                // Let the dictionary return the default IEnumerator from its IEnumerable.GetEnumerator().
                // For IDictionary-derived classes this is normally be IDictionaryEnumerator.
                // For IDictionary<TKey, TVale>-derived classes this is normally IDictionaryEnumerator as well
                // but may be IEnumerable<KeyValuePair<TKey, TValue>> if the dictionary only supports generics.
                state.Current.CollectionEnumerator = enumerable.GetEnumerator();
            }

            if (state.Current.CollectionEnumerator.MoveNext())
            {
                // A dictionary should not have a null KeyValuePair.
                Debug.Assert(state.Current.CollectionEnumerator.Current != null);

                bool   obtainedValues = false;
                string?key            = default;
                object?value          = default;

                // Check for polymorphism.
                if (elementClassInfo.ClassType == ClassType.Unknown)
                {
                    jsonPropertyInfo.GetDictionaryKeyAndValue(ref state.Current, out key, out value);
                    GetRuntimeClassInfo(value, ref elementClassInfo, options);
                    obtainedValues = true;
                }

                if (elementClassInfo.ClassType == ClassType.Value)
                {
                    elementClassInfo.PolicyProperty !.WriteDictionary(ref state, writer);
                }
                else
                {
                    if (!obtainedValues)
                    {
                        jsonPropertyInfo.GetDictionaryKeyAndValue(ref state.Current, out key, out value);
                    }

                    if (options.DictionaryKeyPolicy != null && state.Current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing)
                    {
                        Debug.Assert(key != null);
                        key = options.DictionaryKeyPolicy.ConvertName(key);
                        if (key == null)
                        {
                            ThrowHelper.ThrowInvalidOperationException_SerializerDictionaryKeyNull(options.DictionaryKeyPolicy.GetType());
                        }
                    }

                    // An object or another enumerator requires a new stack frame.
                    state.Push(elementClassInfo, value);

                    state.Current.KeyName = key;
                }

                return(false);
            }

            // We are done enumerating.
            if (state.Current.ExtensionDataStatus == ExtensionDataWriteStatus.Writing)
            {
                state.Current.ExtensionDataStatus = ExtensionDataWriteStatus.Finished;
            }
            else
            {
                writer.WriteEndObject();
            }

            return(WriteEndDictionary(ref state));
        }
コード例 #29
0
        private static void HandleStartObject(JsonSerializerOptions options, ref ReadStack state)
        {
            Debug.Assert(!state.Current.IsProcessingDictionary());

            // Note: unless we are a root object, we are going to push a property onto the ReadStack
            // in the if/else if check below.

            if (state.Current.IsProcessingEnumerable())
            {
                // A nested object within an enumerable (non-dictionary).

                if (!state.Current.CollectionPropertyInitialized)
                {
                    // We have bad JSON: enumerable element appeared without preceding StartArray token.
                    ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(state.Current.JsonPropertyInfo.DeclaredPropertyType);
                }

                Type objType = state.Current.GetElementType();
                state.Push();
                state.Current.Initialize(objType, options);
            }
            else if (state.Current.JsonPropertyInfo != null)
            {
                // Nested object within an object.
                Debug.Assert(state.Current.IsProcessingObject(ClassType.Object));

                Type objType = state.Current.JsonPropertyInfo.RuntimePropertyType;
                state.Push();
                state.Current.Initialize(objType, options);
            }

            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            if (state.Current.IsProcessingObject(ClassType.Dictionary))
            {
                object value = ReadStackFrame.CreateDictionaryValue(ref state);

                // If value is not null, then we don't have a converter so apply the value.
                if (value != null)
                {
                    state.Current.ReturnValue = value;
                    state.Current.DetermineIfDictionaryCanBePopulated(state.Current.ReturnValue);
                }

                state.Current.CollectionPropertyInitialized = true;
            }
            else if (state.Current.IsProcessingObject(ClassType.Object))
            {
                if (classInfo.CreateObject == null)
                {
                    ThrowHelper.ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(classInfo.Type);
                }

                state.Current.ReturnValue = classInfo.CreateObject();
            }
            else
            {
                // Only dictionaries or objects are valid given the `StartObject` token.
                ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(classInfo.Type);
            }
        }
コード例 #30
0
        private static void HandleEndDictionary(JsonSerializerOptions options, ref Utf8JsonReader reader, ref ReadStack state)
        {
            if (state.Current.IsDictionaryProperty)
            {
                // We added the items to the dictionary already.
                state.Current.ResetProperty();
            }
            else if (state.Current.IsIDictionaryConstructibleProperty)
            {
                Debug.Assert(state.Current.TempDictionaryValues != null);
                JsonDictionaryConverter converter = state.Current.JsonPropertyInfo.DictionaryConverter;
                state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, converter.CreateFromDictionary(ref state, state.Current.TempDictionaryValues, options));
                state.Current.ResetProperty();
            }
            else if (state.Current.IsKeyValuePairProperty)
            {
                JsonClassInfo elementClassInfo = state.Current.JsonPropertyInfo.ElementClassInfo;

                JsonPropertyInfo propertyInfo;
                if (elementClassInfo.ClassType == ClassType.KeyValuePair)
                {
                    propertyInfo = elementClassInfo.GetPolicyPropertyOfKeyValuePair();
                }
                else
                {
                    propertyInfo = elementClassInfo.GetPolicyProperty();
                }

                Debug.Assert(state.Current.TempDictionaryValues != null);
                state.Current.JsonPropertyInfo.SetValueAsObject(
                    state.Current.ReturnValue,
                    propertyInfo.CreateKeyValuePairInstance(ref state, state.Current.TempDictionaryValues, options));
                state.Current.ResetProperty();
            }
            else
            {
                object value;
                if (state.Current.TempDictionaryValues != null)
                {
                    if (state.Current.IsKeyValuePair)
                    {
                        JsonClassInfo elementClassInfo = state.Current.JsonClassInfo.ElementClassInfo;

                        JsonPropertyInfo propertyInfo;
                        if (elementClassInfo.ClassType == ClassType.KeyValuePair)
                        {
                            propertyInfo = elementClassInfo.GetPolicyPropertyOfKeyValuePair();
                        }
                        else
                        {
                            propertyInfo = elementClassInfo.GetPolicyProperty();
                        }

                        value = propertyInfo.CreateKeyValuePairInstance(ref state, state.Current.TempDictionaryValues, options);
                    }
                    else
                    {
                        JsonDictionaryConverter converter = state.Current.JsonPropertyInfo.DictionaryConverter;
                        value = converter.CreateFromDictionary(ref state, state.Current.TempDictionaryValues, options);
                    }
                }
                else
                {
                    value = state.Current.ReturnValue;
                }

                if (state.IsLastFrame)
                {
                    // Set the return value directly since this will be returned to the user.
                    state.Current.Reset();
                    state.Current.ReturnValue = value;
                }
                else
                {
                    state.Pop();
                    ApplyObjectToEnumerable(value, ref state, ref reader);
                }
            }
        }