Exemplo n.º 1
0
 // There are three conditions to consider for an object (primitive value, enumerable or object) being processed here:
 // 1) The object type was specified as the root-level return type to a Deserialize method.
 // 2) The object is a property on a parent object.
 // 3) The object is an element in an enumerable.
 private static bool WriteCore(
     Utf8JsonWriter writer,
     object?value,
     JsonSerializerOptions options,
     ref WriteStack state,
     JsonConverter jsonConverter)
 {
     try
     {
         return(jsonConverter.TryWriteAsObject(writer, value, options, ref state));
     }
     catch (InvalidOperationException ex) when(ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException)
     {
         ThrowHelper.ReThrowWithPath(state, ex);
         throw;
     }
     catch (JsonException ex)
     {
         ThrowHelper.AddExceptionInformation(state, ex);
         throw;
     }
 }
Exemplo n.º 2
0
        private static void ReadCore(
            JsonSerializerOptions options,
            ref Utf8JsonReader reader,
            ref ReadStack readStack)
        {
            try
            {
                JsonReaderState initialState         = default;
                long            initialBytesConsumed = default;

                while (true)
                {
                    if (readStack.ReadAhead)
                    {
                        // When we're reading ahead we always have to save the state
                        // as we don't know if the next token is an opening object or
                        // array brace.
                        initialState         = reader.CurrentState;
                        initialBytesConsumed = reader.BytesConsumed;
                    }

                    if (!reader.Read())
                    {
                        // Need more data
                        break;
                    }

                    JsonTokenType tokenType = reader.TokenType;

                    if (options.ReferenceHandling.ShouldReadPreservedReferences())
                    {
                        CheckValidTokenAfterMetadataValues(ref readStack, tokenType);
                    }

                    if (JsonHelpers.IsInRangeInclusive(tokenType, JsonTokenType.String, JsonTokenType.False))
                    {
                        Debug.Assert(tokenType == JsonTokenType.String || tokenType == JsonTokenType.Number || tokenType == JsonTokenType.True || tokenType == JsonTokenType.False);

                        HandleValue(tokenType, options, ref reader, ref readStack);
                    }
                    else if (tokenType == JsonTokenType.PropertyName)
                    {
                        HandlePropertyName(options, ref reader, ref readStack);
                    }
                    else if (tokenType == JsonTokenType.StartObject)
                    {
                        if (readStack.Current.SkipProperty)
                        {
                            readStack.Push();
                            readStack.Current.Drain = true;
                        }
                        else if (readStack.Current.IsProcessingValue())
                        {
                            if (!HandleObjectAsValue(tokenType, options, ref reader, ref readStack, ref initialState, initialBytesConsumed))
                            {
                                // Need more data
                                break;
                            }
                        }
                        else if (readStack.Current.IsProcessingDictionary())
                        {
                            HandleStartDictionary(options, ref readStack);
                        }
                        else
                        {
                            HandleStartObject(options, ref readStack);
                        }
                    }
                    else if (tokenType == JsonTokenType.EndObject)
                    {
                        if (readStack.Current.Drain)
                        {
                            readStack.Pop();

                            // Clear the current property in case it is a dictionary, since dictionaries must have EndProperty() called when completed.
                            // A non-dictionary property can also have EndProperty() called when completed, although it is redundant.
                            readStack.Current.EndProperty();
                        }
                        else if (readStack.Current.ReferenceId != null)
                        {
                            Debug.Assert(options.ReferenceHandling.ShouldReadPreservedReferences());

                            HandleReference(ref readStack);
                        }
                        else if (readStack.Current.IsProcessingDictionary())
                        {
                            HandleEndDictionary(options, ref readStack);
                        }
                        else
                        {
                            HandleEndObject(ref readStack);
                        }
                    }
                    else if (tokenType == JsonTokenType.StartArray)
                    {
                        if (!readStack.Current.IsProcessingValue())
                        {
                            HandleStartArray(options, ref readStack);
                        }
                        else if (!HandleObjectAsValue(tokenType, options, ref reader, ref readStack, ref initialState, initialBytesConsumed))
                        {
                            // Need more data
                            break;
                        }
                    }
                    else if (tokenType == JsonTokenType.EndArray)
                    {
                        HandleEndArray(options, ref readStack);
                    }
                    else if (tokenType == JsonTokenType.Null)
                    {
                        HandleNull(options, ref reader, ref readStack);
                    }
                }
            }
            catch (JsonReaderException ex)
            {
                // Re-throw with Path information.
                ThrowHelper.ReThrowWithPath(readStack, ex);
            }
            catch (FormatException ex) when(ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException)
            {
                ThrowHelper.ReThrowWithPath(readStack, reader, ex);
            }
            catch (InvalidOperationException ex) when(ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException)
            {
                ThrowHelper.ReThrowWithPath(readStack, reader, ex);
            }
            catch (JsonException ex)
            {
                ThrowHelper.AddExceptionInformation(readStack, reader, ex);
                throw;
            }

            readStack.BytesConsumed += reader.BytesConsumed;
        }
Exemplo n.º 3
0
        // There are three conditions to consider for an object (primitive value, enumerable or object) being processed here:
        // 1) The object type was specified as the root-level return type to a Parse\Read method.
        // 2) The object is property on a parent object.
        // 3) The object is an element in an enumerable.
        private static bool Write(
            Utf8JsonWriter writer,
            int flushThreshold,
            JsonSerializerOptions options,
            ref WriteStack state)
        {
            bool finishedSerializing;
            int  currentDepth = writer.CurrentDepth;

            try
            {
                do
                {
                    WriteStackFrame current = state.Current;
                    switch (current.JsonClassInfo.ClassType)
                    {
                    case ClassType.Enumerable:
                        finishedSerializing = HandleEnumerable(current.JsonClassInfo.ElementClassInfo, options, writer, ref state);
                        break;

                    case ClassType.Value:
                        Debug.Assert(current.JsonPropertyInfo.ClassType == ClassType.Value);
                        current.JsonPropertyInfo.Write(ref state, writer);
                        finishedSerializing = true;
                        break;

                    case ClassType.Object:
                        finishedSerializing = WriteObject(options, writer, ref state);
                        break;

                    case ClassType.Dictionary:
                    case ClassType.IDictionaryConstructible:
                        finishedSerializing = HandleDictionary(current.JsonClassInfo.ElementClassInfo, options, writer, ref state);
                        break;

                    default:
                        Debug.Assert(state.Current.JsonClassInfo.ClassType == ClassType.Unknown);

                        // Treat typeof(object) as an empty object.
                        finishedSerializing = WriteObject(options, writer, ref state);
                        break;
                    }

                    if (finishedSerializing)
                    {
                        if (writer.CurrentDepth == 0 || writer.CurrentDepth == currentDepth)
                        {
                            break;
                        }
                    }
                    else if (writer.CurrentDepth >= options.EffectiveMaxDepth)
                    {
                        ThrowHelper.ThrowJsonException_DepthTooLarge(writer.CurrentDepth, state, options);
                    }

                    // If serialization is not yet end and we surpass beyond flush threshold return false and flush stream.
                    if (flushThreshold >= 0 && writer.BytesPending > flushThreshold)
                    {
                        return(false);
                    }
                } while (true);
            }
            catch (InvalidOperationException ex) when(ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException)
            {
                ThrowHelper.ReThrowWithPath(state, ex);
            }
            catch (JsonException ex)
            {
                ThrowHelper.AddExceptionInformation(state, ex);
                throw;
            }

            return(true);
        }
Exemplo n.º 4
0
        private static void ReadCore(
            JsonSerializerOptions options,
            ref Utf8JsonReader reader,
            ref ReadStack readStack)
        {
            try
            {
                JsonReaderState initialState         = default;
                long            initialBytesConsumed = default;

                while (true)
                {
                    if (readStack.ReadAhead)
                    {
                        // When we're reading ahead we always have to save the state
                        // as we don't know if the next token is an opening object or
                        // array brace.
                        initialState         = reader.CurrentState;
                        initialBytesConsumed = reader.BytesConsumed;
                    }

                    if (!reader.Read())
                    {
                        // Need more data
                        break;
                    }

                    JsonTokenType tokenType = reader.TokenType;

                    if (JsonHelpers.IsInRangeInclusive(tokenType, JsonTokenType.String, JsonTokenType.False))
                    {
                        Debug.Assert(tokenType == JsonTokenType.String || tokenType == JsonTokenType.Number || tokenType == JsonTokenType.True || tokenType == JsonTokenType.False);

                        HandleValue(tokenType, options, ref reader, ref readStack);
                    }
                    else if (tokenType == JsonTokenType.PropertyName)
                    {
                        HandlePropertyName(options, ref reader, ref readStack);
                    }
                    else if (tokenType == JsonTokenType.StartObject)
                    {
                        if (readStack.Current.SkipProperty)
                        {
                            readStack.Push();
                            readStack.Current.Drain = true;
                        }
                        else if (readStack.Current.IsProcessingValue(tokenType))
                        {
                            if (!HandleObjectAsValue(tokenType, options, ref reader, ref readStack, ref initialState, initialBytesConsumed))
                            {
                                // Need more data
                                break;
                            }
                        }
                        else if (readStack.Current.IsProcessingDictionary || readStack.Current.IsProcessingIDictionaryConstructible)
                        {
                            HandleStartDictionary(options, ref reader, ref readStack);
                        }
                        else
                        {
                            HandleStartObject(options, ref reader, ref readStack);
                        }
                    }
                    else if (tokenType == JsonTokenType.EndObject)
                    {
                        if (readStack.Current.Drain)
                        {
                            readStack.Pop();
                        }
                        else if (readStack.Current.IsProcessingDictionary || readStack.Current.IsProcessingIDictionaryConstructible)
                        {
                            HandleEndDictionary(options, ref reader, ref readStack);
                        }
                        else
                        {
                            HandleEndObject(options, ref reader, ref readStack);
                        }
                    }
                    else if (tokenType == JsonTokenType.StartArray)
                    {
                        if (!readStack.Current.IsProcessingValue(tokenType))
                        {
                            HandleStartArray(options, ref reader, ref readStack);
                        }
                        else if (!HandleObjectAsValue(tokenType, options, ref reader, ref readStack, ref initialState, initialBytesConsumed))
                        {
                            // Need more data
                            break;
                        }
                    }
                    else if (tokenType == JsonTokenType.EndArray)
                    {
                        HandleEndArray(options, ref reader, ref readStack);
                    }
                    else if (tokenType == JsonTokenType.Null)
                    {
                        HandleNull(ref reader, ref readStack, options);
                    }
                }
            }
            catch (JsonReaderException ex)
            {
                // Re-throw with Path information.
                ThrowHelper.ReThrowWithPath(readStack, ex);
            }
            catch (FormatException ex) when(ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException)
            {
                ThrowHelper.ReThrowWithPath(readStack, reader, ex);
            }
            catch (InvalidOperationException ex) when(ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException)
            {
                ThrowHelper.ReThrowWithPath(readStack, reader, ex);
            }
            catch (JsonException ex)
            {
                ThrowHelper.AddExceptionInformation(readStack, reader, ex);
                throw;
            }

            readStack.BytesConsumed += reader.BytesConsumed;
            return;
        }
Exemplo n.º 5
0
        private static void ReadCore(
            JsonSerializerOptions options,
            ref Utf8JsonReader reader,
            ref ReadStack state)
        {
            try
            {
                JsonPropertyInfo jsonPropertyInfo = state.Current.JsonClassInfo !.PolicyProperty !;
                JsonConverter    converter        = jsonPropertyInfo.ConverterBase;

                if (!state.IsContinuation)
                {
                    if (!JsonConverter.SingleValueReadWithReadAhead(converter.ClassType, ref reader, ref state))
                    {
                        // Read more data until we have the full element.
                        state.BytesConsumed += reader.BytesConsumed;
                        return;
                    }
                }
                else
                {
                    // For a continuation, read ahead here to avoid having to build and then tear
                    // down the call stack if there is more than one buffer fetch necessary.
                    if (!JsonConverter.SingleValueReadWithReadAhead(ClassType.Value, ref reader, ref state))
                    {
                        state.BytesConsumed += reader.BytesConsumed;
                        return;
                    }
                }

                bool success = converter.TryReadAsObject(ref reader, jsonPropertyInfo.RuntimePropertyType !, options, ref state, out object?value);
                if (success)
                {
                    state.Current.ReturnValue = value;

                    // Read any trailing whitespace.
                    // If additional whitespace exists after this read, the subsequent call to reader.Read() will throw.
                    reader.Read();
                }

                state.BytesConsumed += reader.BytesConsumed;
            }
            catch (JsonReaderException ex)
            {
                // Re-throw with Path information.
                ThrowHelper.ReThrowWithPath(state, ex);
            }
            catch (FormatException ex) when(ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException)
            {
                ThrowHelper.ReThrowWithPath(state, reader, ex);
            }
            catch (InvalidOperationException ex) when(ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException)
            {
                ThrowHelper.ReThrowWithPath(state, reader, ex);
            }
            catch (JsonException ex)
            {
                ThrowHelper.AddExceptionInformation(state, reader, ex);
                throw;
            }
        }
Exemplo n.º 6
0
        // There are three conditions to consider for an object (primitive value, enumerable or object) being processed here:
        // 1) The object type was specified as the root-level return type to a Deserialize method.
        // 2) The object is a property on a parent object.
        // 3) The object is an element in an enumerable.
        private static bool Write(
            Utf8JsonWriter writer,
            int originalWriterDepth,
            int flushThreshold,
            JsonSerializerOptions options,
            ref WriteStack state)
        {
            bool finishedSerializing;

            try
            {
                do
                {
                    switch (state.Current.JsonClassInfo.ClassType)
                    {
                    case ClassType.Enumerable:
                        finishedSerializing = HandleEnumerable(state.Current.JsonClassInfo.ElementClassInfo, options, writer, ref state);
                        break;

                    case ClassType.Value:
                        Debug.Assert(state.Current.JsonPropertyInfo.ClassType == ClassType.Value);
                        state.Current.JsonPropertyInfo.Write(ref state, writer);
                        finishedSerializing = true;
                        break;

                    case ClassType.Dictionary:
                        finishedSerializing = HandleDictionary(state.Current.JsonClassInfo.ElementClassInfo, options, writer, ref state);
                        break;

                    default:
                        Debug.Assert(state.Current.JsonClassInfo.ClassType == ClassType.Object ||
                                     state.Current.JsonClassInfo.ClassType == ClassType.Unknown);

                        finishedSerializing = WriteObject(options, writer, ref state);
                        break;
                    }

                    if (finishedSerializing)
                    {
                        if (writer.CurrentDepth == originalWriterDepth)
                        {
                            break;
                        }
                    }
                    else if (writer.CurrentDepth >= options.EffectiveMaxDepth)
                    {
                        ThrowHelper.ThrowInvalidOperationException_SerializerCycleDetected(options.MaxDepth);
                    }

                    // If serialization is not finished and we surpass flush threshold then return false which will flush stream.
                    if (flushThreshold >= 0 && writer.BytesPending > flushThreshold)
                    {
                        return(false);
                    }
                } while (true);
            }
            catch (InvalidOperationException ex) when(ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException)
            {
                ThrowHelper.ReThrowWithPath(state, ex);
            }
            catch (JsonException ex)
            {
                ThrowHelper.AddExceptionInformation(state, ex);
                throw;
            }

            return(true);
        }