コード例 #1
0
        protected override void CreateCollection(ref Utf8JsonReader reader, ref ReadStack state, JsonSerializerOptions options)
        {
            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            if (TypeToConvert.IsInterface || TypeToConvert.IsAbstract)
            {
                if (!TypeToConvert.IsAssignableFrom(RuntimeType))
                {
                    ThrowHelper.ThrowNotSupportedException_CannotPopulateCollection(TypeToConvert, ref reader, ref state);
                }

                state.Current.ReturnValue = new HashSet <TElement>();
            }
            else
            {
                if (classInfo.CreateObject == null)
                {
                    ThrowHelper.ThrowNotSupportedException_DeserializeNoDeserializationConstructor(TypeToConvert, ref reader, ref state);
                }

                TCollection returnValue = (TCollection)classInfo.CreateObject() !;

                if (returnValue.IsReadOnly)
                {
                    ThrowHelper.ThrowNotSupportedException_CannotPopulateCollection(TypeToConvert, ref reader, ref state);
                }

                state.Current.ReturnValue = returnValue;
            }
        }
コード例 #2
0
ファイル: IListConverter.cs プロジェクト: lateralusX/runtime
        protected override void CreateCollection(ref ReadStack state, JsonSerializerOptions options)
        {
            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            if (TypeToConvert.IsInterface || TypeToConvert.IsAbstract)
            {
                if (!TypeToConvert.IsAssignableFrom(RuntimeType))
                {
                    ThrowHelper.ThrowNotSupportedException_DeserializeNoParameterlessConstructor(TypeToConvert);
                }

                state.Current.ReturnValue = new List <object?>();
            }
            else
            {
                if (classInfo.CreateObject == null)
                {
                    ThrowHelper.ThrowNotSupportedException_DeserializeNoParameterlessConstructor(TypeToConvert);
                }

                TCollection returnValue = (TCollection)classInfo.CreateObject() !;

                if (returnValue.IsReadOnly)
                {
                    ThrowHelper.ThrowNotSupportedException_SerializationNotSupported(TypeToConvert);
                }

                state.Current.ReturnValue = returnValue;
            }
        }
コード例 #3
0
        protected override void CreateCollection(ref ReadStack state, JsonSerializerOptions options)
        {
            if (!TypeToConvert.IsAssignableFrom(RuntimeType))
            {
                ThrowHelper.ThrowNotSupportedException_DeserializeNoParameterlessConstructor(TypeToConvert);
            }

            state.Current.ReturnValue = new List <TElement>();
        }
コード例 #4
0
        protected override void CreateCollection(ref Utf8JsonReader reader, ref ReadStack state, JsonSerializerOptions options)
        {
            if (!TypeToConvert.IsAssignableFrom(RuntimeType))
            {
                ThrowHelper.ThrowNotSupportedException_CannotPopulateCollection(TypeToConvert, ref reader, ref state);
            }

            state.Current.ReturnValue = new List <TElement>();
        }
コード例 #5
0
        /// <summary>
        /// Initializes the state for polymorphic cases and returns the appropriate derived converter.
        /// </summary>
        internal JsonConverter?ResolvePolymorphicConverter(JsonTypeInfo jsonTypeInfo, JsonSerializerOptions options, ref ReadStack state)
        {
            Debug.Assert(!IsValueType);
            Debug.Assert(CanHaveMetadata);
            Debug.Assert(state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Type));
            Debug.Assert(state.Current.PolymorphicSerializationState != PolymorphicSerializationState.PolymorphicReEntryStarted);
            Debug.Assert(jsonTypeInfo.PolymorphicTypeResolver?.UsesTypeDiscriminators == true);

            JsonConverter?polymorphicConverter = null;

            switch (state.Current.PolymorphicSerializationState)
            {
            case PolymorphicSerializationState.None:
                Debug.Assert(!state.IsContinuation);
                Debug.Assert(state.PolymorphicTypeDiscriminator != null);

                PolymorphicTypeResolver resolver = jsonTypeInfo.PolymorphicTypeResolver;
                if (resolver.TryGetDerivedJsonTypeInfo(state.PolymorphicTypeDiscriminator, out JsonTypeInfo? resolvedType))
                {
                    Debug.Assert(TypeToConvert.IsAssignableFrom(resolvedType.Type));

                    polymorphicConverter = state.InitializePolymorphicReEntry(resolvedType);
                    if (!polymorphicConverter.CanHaveMetadata)
                    {
                        ThrowHelper.ThrowNotSupportedException_DerivedConverterDoesNotSupportMetadata(resolvedType.Type);
                    }
                }
                else
                {
                    state.Current.PolymorphicSerializationState = PolymorphicSerializationState.PolymorphicReEntryNotFound;
                }

                state.PolymorphicTypeDiscriminator = null;
                break;

            case PolymorphicSerializationState.PolymorphicReEntrySuspended:
                polymorphicConverter = state.ResumePolymorphicReEntry();
                Debug.Assert(TypeToConvert.IsAssignableFrom(polymorphicConverter.TypeToConvert));
                break;

            case PolymorphicSerializationState.PolymorphicReEntryNotFound:
                Debug.Assert(state.Current.PolymorphicJsonTypeInfo is null);
                break;

            default:
                Debug.Fail("Unexpected PolymorphicSerializationState.");
                break;
            }

            return(polymorphicConverter);
        }
コード例 #6
0
        /// <summary>
        /// When overidden, constructs a new <see cref="JsonConverter{T}"/> instance.
        /// </summary>
        protected internal JsonConverter()
        {
            // Today only typeof(object) can have polymorphic writes.
            // In the future, this will be check for !IsSealed (and excluding value types).
            CanBePolymorphic    = TypeToConvert == JsonClassInfo.ObjectType;
            IsValueType         = TypeToConvert.IsValueType;
            CanBeNull           = !IsValueType || TypeToConvert.IsNullableOfT();
            IsInternalConverter = GetType().Assembly == typeof(JsonConverter).Assembly;

            if (HandleNull)
            {
                HandleNullOnRead  = true;
                HandleNullOnWrite = true;
            }

            // For the HandleNull == false case, either:
            // 1) The default values are assigned in this type's virtual HandleNull property
            // or
            // 2) A converter overroad HandleNull and returned false so HandleNullOnRead and HandleNullOnWrite
            // will be their default values of false.

            CanUseDirectReadOrWrite = !CanBePolymorphic && IsInternalConverter && ClassType == ClassType.Value;
        }
コード例 #7
0
ファイル: JsonConverterOfT.cs プロジェクト: edevoogd/runtime
        internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, out T?value)
        {
            if (ConverterStrategy == ConverterStrategy.Value)
            {
                // A value converter should never be within a continuation.
                Debug.Assert(!state.IsContinuation);

                // For perf and converter simplicity, handle null here instead of forwarding to the converter.
                if (reader.TokenType == JsonTokenType.Null && !HandleNullOnRead)
                {
                    if (!CanBeNull)
                    {
                        ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert);
                    }

                    value = default;
                    return(true);
                }

#if !DEBUG
                // For performance, only perform validation on internal converters on debug builds.
                if (IsInternalConverter)
                {
                    if (state.Current.NumberHandling != null)
                    {
                        value = ReadNumberWithCustomHandling(ref reader, state.Current.NumberHandling.Value, options);
                    }
                    else
                    {
                        value = Read(ref reader, typeToConvert, options);
                    }
                }
                else
#endif
                {
                    JsonTokenType originalPropertyTokenType     = reader.TokenType;
                    int           originalPropertyDepth         = reader.CurrentDepth;
                    long          originalPropertyBytesConsumed = reader.BytesConsumed;

                    if (state.Current.NumberHandling != null)
                    {
                        value = ReadNumberWithCustomHandling(ref reader, state.Current.NumberHandling.Value, options);
                    }
                    else
                    {
                        value = Read(ref reader, typeToConvert, options);
                    }

                    VerifyRead(
                        originalPropertyTokenType,
                        originalPropertyDepth,
                        originalPropertyBytesConsumed,
                        isValueConverter: true,
                        ref reader);
                }

                if (options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve &&
                    CanBePolymorphic && value is JsonElement element)
                {
                    // Edge case where we want to lookup for a reference when parsing into typeof(object)
                    // instead of return `value` as a JsonElement.
                    Debug.Assert(TypeToConvert == typeof(object));

                    if (JsonSerializer.TryGetReferenceFromJsonElement(ref state, element, out object?referenceValue))
                    {
                        value = (T?)referenceValue;
                    }
                }

                return(true);
            }

            bool success;

            // Remember if we were a continuation here since Push() may affect IsContinuation.
            bool wasContinuation = state.IsContinuation;

#if DEBUG
            // DEBUG: ensure push/pop operations preserve stack integrity
            JsonTypeInfo originalJsonTypeInfo = state.Current.JsonTypeInfo;
#endif
            state.Push();
            Debug.Assert(TypeToConvert.IsAssignableFrom(state.Current.JsonTypeInfo.Type));

#if !DEBUG
            // For performance, only perform validation on internal converters on debug builds.
            if (IsInternalConverter)
            {
                if (reader.TokenType == JsonTokenType.Null && !HandleNullOnRead && !wasContinuation)
                {
                    if (!CanBeNull)
                    {
                        ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert);
                    }

                    // For perf and converter simplicity, handle null here instead of forwarding to the converter.
                    value   = default;
                    success = true;
                }
                else
                {
                    success = OnTryRead(ref reader, typeToConvert, options, ref state, out value);
                }
            }
            else
#endif
            {
                if (!wasContinuation)
                {
                    // For perf and converter simplicity, handle null here instead of forwarding to the converter.
                    if (reader.TokenType == JsonTokenType.Null && !HandleNullOnRead)
                    {
                        if (!CanBeNull)
                        {
                            ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert);
                        }

                        value = default;
                        state.Pop(true);
#if DEBUG
                        Debug.Assert(ReferenceEquals(originalJsonTypeInfo, state.Current.JsonTypeInfo));
#endif
                        return(true);
                    }

                    Debug.Assert(state.Current.OriginalTokenType == JsonTokenType.None);
                    state.Current.OriginalTokenType = reader.TokenType;

                    Debug.Assert(state.Current.OriginalDepth == 0);
                    state.Current.OriginalDepth = reader.CurrentDepth;
                }

                success = OnTryRead(ref reader, typeToConvert, options, ref state, out value);
                if (success)
                {
                    if (state.IsContinuation)
                    {
                        // The resumable converter did not forward to the next converter that previously returned false.
                        ThrowHelper.ThrowJsonException_SerializationConverterRead(this);
                    }

                    VerifyRead(
                        state.Current.OriginalTokenType,
                        state.Current.OriginalDepth,
                        bytesConsumed: 0,
                        isValueConverter: false,
                        ref reader);

                    // No need to clear state.Current.* since a stack pop will occur.
                }
            }

            state.Pop(success);
#if DEBUG
            Debug.Assert(ReferenceEquals(originalJsonTypeInfo, state.Current.JsonTypeInfo));
#endif
            return(success);
        }
コード例 #8
0
        /// <summary>
        /// Initializes the state for polymorphic cases and returns the appropriate derived converter.
        /// </summary>
        internal JsonConverter?ResolvePolymorphicConverter(object value, JsonTypeInfo jsonTypeInfo, JsonSerializerOptions options, ref WriteStack state)
        {
            Debug.Assert(!IsValueType);
            Debug.Assert(value != null && TypeToConvert.IsAssignableFrom(value.GetType()));
            Debug.Assert(CanBePolymorphic || jsonTypeInfo.PolymorphicTypeResolver != null);
            Debug.Assert(state.PolymorphicTypeDiscriminator is null);

            JsonConverter?polymorphicConverter = null;

            switch (state.Current.PolymorphicSerializationState)
            {
            case PolymorphicSerializationState.None:
                Debug.Assert(!state.IsContinuation);

                Type runtimeType = value.GetType();

                if (jsonTypeInfo.PolymorphicTypeResolver is PolymorphicTypeResolver resolver)
                {
                    Debug.Assert(CanHaveMetadata);

                    if (resolver.TryGetDerivedJsonTypeInfo(runtimeType, out JsonTypeInfo? derivedJsonTypeInfo, out string?typeDiscriminatorId))
                    {
                        polymorphicConverter = state.Current.InitializePolymorphicReEntry(derivedJsonTypeInfo);

                        if (typeDiscriminatorId is not null)
                        {
                            if (!polymorphicConverter.CanHaveMetadata)
                            {
                                ThrowHelper.ThrowNotSupportedException_DerivedConverterDoesNotSupportMetadata(derivedJsonTypeInfo.Type);
                            }

                            state.PolymorphicTypeDiscriminator = typeDiscriminatorId;
                        }
                    }
                    else
                    {
                        state.Current.PolymorphicSerializationState = PolymorphicSerializationState.PolymorphicReEntryNotFound;
                    }
                }
                else
                {
                    Debug.Assert(CanBePolymorphic);

                    if (runtimeType != TypeToConvert)
                    {
                        polymorphicConverter = state.Current.InitializePolymorphicReEntry(runtimeType, options);
                    }
                    else
                    {
                        state.Current.PolymorphicSerializationState = PolymorphicSerializationState.PolymorphicReEntryNotFound;
                    }
                }
                break;

            case PolymorphicSerializationState.PolymorphicReEntrySuspended:
                Debug.Assert(state.IsContinuation);
                polymorphicConverter = state.Current.ResumePolymorphicReEntry();
                Debug.Assert(TypeToConvert.IsAssignableFrom(polymorphicConverter.TypeToConvert));
                break;

            case PolymorphicSerializationState.PolymorphicReEntryNotFound:
                Debug.Assert(state.IsContinuation);
                break;

            default:
                Debug.Fail("Unexpected PolymorphicSerializationState.");
                break;
            }

            return(polymorphicConverter);
        }
コード例 #9
0
        public override MethodInfo[] GetAdditionalDataMethod()
        {
            var mi = TypeToConvert.GetMethod(nameof(TimeZoneInfo.GetAdjustmentRules));

            return(new MethodInfo[] { mi });
        }
コード例 #10
0
        /// <summary>
        /// Initializes the state for polymorphic cases and returns the appropriate derived converter.
        /// </summary>
        internal JsonConverter?ResolvePolymorphicConverter(object value, JsonTypeInfo jsonTypeInfo, JsonSerializerOptions options, ref WriteStack state)
        {
            Debug.Assert(!IsValueType);
            Debug.Assert(value != null && TypeToConvert.IsAssignableFrom(value.GetType()));
            Debug.Assert(CanBePolymorphic || jsonTypeInfo.PolymorphicTypeResolver != null);
            Debug.Assert(state.PolymorphicTypeDiscriminator is null);

            JsonConverter?polymorphicConverter = null;

            switch (state.Current.PolymorphicSerializationState)
            {
            case PolymorphicSerializationState.None:
                Debug.Assert(!state.IsContinuation);

                if (state.IsPolymorphicRootValue && state.CurrentDepth == 0)
                {
                    Debug.Assert(jsonTypeInfo.PolymorphicTypeResolver != null);

                    // We're serializing a root-level object value whose runtime type uses type hierarchies.
                    // For consistency with nested value handling, we want to serialize as-is without emitting metadata.
                    state.Current.PolymorphicSerializationState = PolymorphicSerializationState.PolymorphicReEntryNotFound;
                    break;
                }

                Type runtimeType = value.GetType();

                if (jsonTypeInfo.PolymorphicTypeResolver is PolymorphicTypeResolver resolver)
                {
                    Debug.Assert(CanHaveMetadata);

                    if (resolver.TryGetDerivedJsonTypeInfo(runtimeType, out JsonTypeInfo? derivedJsonTypeInfo, out object?typeDiscriminator))
                    {
                        polymorphicConverter = state.Current.InitializePolymorphicReEntry(derivedJsonTypeInfo);

                        if (typeDiscriminator is not null)
                        {
                            if (!polymorphicConverter.CanHaveMetadata)
                            {
                                ThrowHelper.ThrowNotSupportedException_DerivedConverterDoesNotSupportMetadata(derivedJsonTypeInfo.Type);
                            }

                            state.PolymorphicTypeDiscriminator = typeDiscriminator;
                        }
                    }
                    else
                    {
                        state.Current.PolymorphicSerializationState = PolymorphicSerializationState.PolymorphicReEntryNotFound;
                    }
                }
                else
                {
                    Debug.Assert(CanBePolymorphic);

                    if (runtimeType != TypeToConvert)
                    {
                        polymorphicConverter = state.Current.InitializePolymorphicReEntry(runtimeType, options);
                    }
                    else
                    {
                        state.Current.PolymorphicSerializationState = PolymorphicSerializationState.PolymorphicReEntryNotFound;
                    }
                }
                break;

            case PolymorphicSerializationState.PolymorphicReEntrySuspended:
                Debug.Assert(state.IsContinuation);
                polymorphicConverter = state.Current.ResumePolymorphicReEntry();
                Debug.Assert(TypeToConvert.IsAssignableFrom(polymorphicConverter.TypeToConvert));
                break;

            case PolymorphicSerializationState.PolymorphicReEntryNotFound:
                Debug.Assert(state.IsContinuation);
                break;

            default:
                Debug.Fail("Unexpected PolymorphicSerializationState.");
                break;
            }

            return(polymorphicConverter);
        }