예제 #1
0
        /// <summary>
        /// Asynchronously reads the next node from the <paramref name="jsonReader"/> and verifies that it is a PrimitiveValue node of type double.
        /// </summary>
        /// <param name="jsonReader">The <see cref="JsonReader"/> to read from.</param>
        /// <returns>A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains the double value read from the reader;
        /// throws an exception if no double value could be read.</returns>
        internal static async Task <double?> ReadDoubleValueAsync(this IJsonReaderAsync jsonReader)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");

            object value = await jsonReader.ReadPrimitiveValueAsync()
                           .ConfigureAwait(false);

            double?doubleValue = value as double?;

            if (value == null || doubleValue != null)
            {
                return(doubleValue);
            }

            int?intValue = value as int?;

            if (intValue != null)
            {
                return((double)intValue);
            }

            decimal?decimalValue = value as decimal?;

            if (decimalValue != null)
            {
                return((double)decimalValue);
            }

            throw CreateException(Strings.JsonReaderExtensions_CannotReadValueAsDouble(value));
        }
예제 #2
0
        /// <summary>
        /// Asynchronously skips over a JSON value (primitive, object or array).
        /// </summary>
        /// <param name="jsonReader">The <see cref="JsonReader"/> to read from.</param>
        /// <remarks>
        /// Pre-Condition: JsonNodeType.PrimitiveValue, JsonNodeType.StartArray or JsonNodeType.StartObject
        /// Post-Condition: JsonNodeType.PrimitiveValue, JsonNodeType.EndArray or JsonNodeType.EndObject
        /// </remarks>
        /// <returns>A task that represents the asynchronous read operation.</returns>
        internal static async Task SkipValueAsync(this IJsonReaderAsync jsonReader)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");
            int depth = 0;

            do
            {
                switch (jsonReader.NodeType)
                {
                case JsonNodeType.StartArray:
                case JsonNodeType.StartObject:
                    depth++;
                    break;

                case JsonNodeType.EndArray:
                case JsonNodeType.EndObject:
                    Debug.Assert(depth > 0, "Seen too many scope ends.");
                    depth--;
                    break;

                default:
                    Debug.Assert(
                        jsonReader.NodeType != JsonNodeType.EndOfInput,
                        "We should not have reached end of input, since the scopes should be well formed. Otherwise JsonReader should have failed by now.");
                    break;
                }
            }while (await jsonReader.ReadAsync().ConfigureAwait(false) && depth > 0);

            if (depth > 0)
            {
                // Not all open scopes were closed:
                // "Invalid JSON. Unexpected end of input was found in JSON content. Not all object and array scopes were closed."
                throw CreateException(Strings.JsonReader_EndOfInputWithOpenScope);
            }
        }
예제 #3
0
        internal static async Task <bool> TryReadNullValueAsync(
#endif
            IJsonReaderAsync jsonReader,
            ODataInputContext inputContext,
            IEdmTypeReference expectedTypeReference,
            bool validateNullValue,
            string propertyName,
            bool?isDynamicProperty = null)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");
            Debug.Assert(inputContext != null, "inputContext != null");

            if (jsonReader.NodeType == JsonNodeType.PrimitiveValue &&
                await jsonReader.GetValueAsync().ConfigureAwait(false) == null)
            {
                await jsonReader.ReadNextAsync()
                .ConfigureAwait(false);

                // NOTE: when reading a null value we will never ask the type resolver (if present) to resolve the
                //       type; we always fall back to the expected type.
                inputContext.MessageReaderSettings.Validator.ValidateNullValue(
                    expectedTypeReference,
                    validateNullValue,
                    propertyName,
                    isDynamicProperty);

                return(true);
            }

            return(false);
        }
예제 #4
0
        /// <summary>
        /// Asynchronously reads the next node from the <paramref name="jsonReader"/> and verifies that it is of the expected node type.
        /// </summary>
        /// <param name="jsonReader">The <see cref="JsonReader"/> to read from.</param>
        /// <param name="expectedNodeType">The expected <see cref="JsonNodeType"/> of the read node.</param>
        private static async Task ReadNextAsync(this IJsonReaderAsync jsonReader, JsonNodeType expectedNodeType)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");
            Debug.Assert(expectedNodeType != JsonNodeType.None, "expectedNodeType != JsonNodeType.None");

            jsonReader.ValidateNodeType(expectedNodeType);
            await jsonReader.ReadAsync().ConfigureAwait(false);
        }
예제 #5
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="jsonBatchReader">The Json batch reader.</param>
        private ODataJsonLightBatchPayloadItemPropertiesCache(ODataJsonLightBatchReader jsonBatchReader)
        {
            Debug.Assert(jsonBatchReader != null, $"{nameof(jsonBatchReader)} != null");

            this.jsonReader             = jsonBatchReader.JsonLightInputContext.JsonReader;
            this.asynchronousJsonReader = jsonBatchReader.JsonLightInputContext.JsonReader;
            this.listener = jsonBatchReader;
        }
예제 #6
0
        /// <summary>
        /// Validates that the asynchronous reader is positioned on the specified node type.
        /// </summary>
        /// <param name="jsonReader">The <see cref="JsonReader"/> to use.</param>
        /// <param name="expectedNodeType">The expected node type.</param>
        private static void ValidateNodeType(this IJsonReaderAsync jsonReader, JsonNodeType expectedNodeType)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");
            Debug.Assert(expectedNodeType != JsonNodeType.None, "expectedNodeType != JsonNodeType.None");

            if (jsonReader.NodeType != expectedNodeType)
            {
                throw CreateException(Strings.JsonReaderExtensions_UnexpectedNodeDetected(expectedNodeType, jsonReader.NodeType));
            }
        }
예제 #7
0
        /// <summary>
        /// Verifies that the current node is a property node and returns the property name.
        /// </summary>
        /// <param name="jsonReader">The <see cref="JsonReader"/> to read from.</param>
        /// <returns>A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains the property name of the current property node.</returns>
        internal static async Task <string> GetPropertyNameAsync(this IJsonReaderAsync jsonReader)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");
            Debug.Assert(jsonReader.NodeType == JsonNodeType.Property, "jsonReader.NodeType == JsonNodeType.Property");

            // NOTE: the JSON reader already verifies that property names are strings and not null/empty
            object value = await jsonReader.GetValueAsync()
                           .ConfigureAwait(false);

            return((string)value);
        }
예제 #8
0
        /// <summary>
        /// Asynchronously reads the next node from the <paramref name="jsonReader"/> and verifies that it is a PrimitiveValue node.
        /// </summary>
        /// <param name="jsonReader">The <see cref="JsonReader"/> to read from.</param>
        /// <returns>A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains the primitive value read from the reader.</returns>
        internal static async Task <object> ReadPrimitiveValueAsync(this IJsonReaderAsync jsonReader)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");

            object value = await jsonReader.GetValueAsync()
                           .ConfigureAwait(false);

            await ReadNextAsync(jsonReader, JsonNodeType.PrimitiveValue)
            .ConfigureAwait(false);

            return(value);
        }
        /// <summary>
        /// Asynchronously populates the body content the Json reader is referencing.
        /// Since the content-type header might not be available at this point (when "headers" attribute
        /// is read after the "body" attribute), if the content-type is not json the body content is
        /// first stored into a string which will be used to populate the stream when the content-type
        /// header is read later.
        /// </summary>
        /// <param name="jsonReader">The Json reader providing access to the data.</param>
        /// <param name="contentTypeHeader">The request's content-type header value.</param>
        /// <returns>
        /// A task that represents the asynchronous write operation.
        /// The value of the TResult parameter contains true if body content is written to stream; false otherwise.
        /// </returns>
        internal async Task <bool> PopulateBodyContentAsync(IJsonReaderAsync jsonReader, string contentTypeHeader)
        {
            bool isStreamPopulated = false;

            BatchPayloadBodyContentType?contentType = DetectBatchPayloadBodyContentType(jsonReader, contentTypeHeader);

            if (contentType == null)
            {
                // We don't have deterministic content-type, cache the string content.
                Debug.Assert(jsonReader.NodeType == JsonNodeType.PrimitiveValue, "jsonReader.NodeType == JsonNodeType.PrimitiveValue");
                this.cachedBodyContent = await jsonReader.ReadStringValueAsync()
                                         .ConfigureAwait(false);

                Debug.Assert(isStreamPopulated == false, "isStreamPopulated == false");
            }
            else
            {
                // We have content-type figured out and should be able to populate the stream.
                switch (contentType)
                {
                case BatchPayloadBodyContentType.Json:
                    await WriteJsonContentAsync(jsonReader)
                    .ConfigureAwait(false);

                    break;

                case BatchPayloadBodyContentType.Textual:
                    string bodyContent = string.Format(CultureInfo.InvariantCulture,
                                                       "\"{0}\"", jsonReader.ReadStringValue());
                    await WriteBytesAsync(Encoding.UTF8.GetBytes(bodyContent))
                    .ConfigureAwait(false);

                    break;

                case BatchPayloadBodyContentType.Binary:
                    // Body content is a base64url encoded string. We could have used HttpServerUtility.UrlTokenDecode(string)
                    // directly but it would introduce new dependency of System.Web.dll.
                    string encoded = await jsonReader.ReadStringValueAsync()
                                     .ConfigureAwait(false);
                    await WriteBinaryContentAsync(encoded)
                    .ConfigureAwait(false);

                    break;

                default:
                    throw new ODataException(Strings.ODataJsonLightBatchBodyContentReaderStream_UnsupportedContentTypeInHeader(contentType));
                }

                isStreamPopulated = true;
            }

            return(isStreamPopulated);
        }
예제 #10
0
        /// <summary>
        /// Asynchronously reads the next node from the <paramref name="jsonReader"/>, verifies that it is a Property node and returns the property name.
        /// </summary>
        /// <param name="jsonReader">The <see cref="JsonReader"/> to read from.</param>
        /// <returns>A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains the property name of the property node read.</returns>
        internal static async Task <string> ReadPropertyNameAsync(this IJsonReaderAsync jsonReader)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");

            jsonReader.ValidateNodeType(JsonNodeType.Property);
            string propertyName = await jsonReader.GetPropertyNameAsync()
                                  .ConfigureAwait(false);

            await jsonReader.ReadNextAsync()
            .ConfigureAwait(false);

            return(propertyName);
        }
예제 #11
0
        /// <summary>
        /// Asynchronously reads the next node from the <paramref name="jsonReader"/> as an <see cref="ODataUntypedValue"/>.
        /// </summary>
        /// <param name="jsonReader">The reader to inspect.</param>
        /// <returns>A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains the <see cref="ODataUntypedValue"/> value read from the reader.</returns>
        internal static async Task <ODataValue> ReadAsUntypedOrNullValueAsync(this IJsonReaderAsync jsonReader)
        {
            StringBuilder builder = new StringBuilder();
            await jsonReader.SkipValueAsync(builder)
            .ConfigureAwait(false);

            Debug.Assert(builder.Length > 0, "builder.Length > 0");

            return(new ODataUntypedValue()
            {
                RawValue = builder.ToString(),
            });
        }
예제 #12
0
        /// <summary>
        /// Asynchronously reads the next node. Use this instead of the direct call to Read since this asserts that there actually is a next node.
        /// </summary>
        /// <param name="jsonReader">The <see cref="JsonReader"/> to read from.</param>
        /// <returns>A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains the node type of the node that reader is positioned on after reading.</returns>
        internal static async Task <JsonNodeType> ReadNextAsync(this IJsonReaderAsync jsonReader)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");

#if DEBUG
            bool result = await jsonReader.ReadAsync()
                          .ConfigureAwait(false);

            Debug.Assert(result, "JsonReader.Read returned false in an unexpected place.");
#else
            await jsonReader.ReadAsync();
#endif
            return(jsonReader.NodeType);
        }
예제 #13
0
        /// <summary>
        /// Try and parse spatial type from the json payload.
        /// </summary>
        /// <param name="jsonReader">The JSON reader to read from.</param>
        /// <param name="insideJsonObjectValue">true if the reader is positioned on the first property of the value which is a JSON Object
        ///     (or the second property if the first one was odata.type).</param>
        /// <param name="inputContext">The input context with all the settings.</param>
        /// <param name="expectedValueTypeReference">Expected edm property type.</param>
        /// <param name="validateNullValue">true to validate null values; otherwise false.</param>
        /// <param name="recursionDepth">The recursion depth to start with.</param>
        /// <param name="propertyName">The name of the property whose value is being read, if applicable (used for error reporting).</param>
        /// <returns>An instance of the spatial type.</returns>
        internal static async Task <ISpatial> ReadSpatialValueAsync(
            IJsonReaderAsync jsonReader,
            bool insideJsonObjectValue,
            ODataInputContext inputContext,
            IEdmPrimitiveTypeReference expectedValueTypeReference,
            bool validateNullValue,
            int recursionDepth,
            string propertyName)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");
            Debug.Assert(inputContext != null, "inputContext != null");
            Debug.Assert(expectedValueTypeReference != null, "expectedValueTypeReference != null");
            Debug.Assert(expectedValueTypeReference.IsSpatial(), "TryParseSpatialType must be called only with spatial types");

            // Spatial value can be either null constant or a JSON object
            // If it's a null primitive value, report a null value.
            if (!insideJsonObjectValue &&
                await TryReadNullValueAsync(jsonReader, inputContext, expectedValueTypeReference, validateNullValue, propertyName)
                .ConfigureAwait(false))
            {
                return(null);
            }

            ISpatial spatialValue = null;

            if (insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject)
            {
                Dictionary <string, object> jsonObject = await ReadObjectValueAsync(jsonReader, insideJsonObjectValue, inputContext, recursionDepth)
                                                         .ConfigureAwait(false);

                GeoJsonObjectFormatter jsonObjectFormatter =
                    SpatialImplementation.CurrentImplementation.CreateGeoJsonObjectFormatter();
                if (expectedValueTypeReference.IsGeography())
                {
                    spatialValue = jsonObjectFormatter.Read <Geography>(jsonObject);
                }
                else
                {
                    spatialValue = jsonObjectFormatter.Read <Geometry>(jsonObject);
                }
            }

            if (spatialValue == null)
            {
                throw new ODataException(ODataErrorStrings.ODataJsonReaderCoreUtils_CannotReadSpatialPropertyValue);
            }

            return(spatialValue);
        }
        /// <summary>
        /// Asynchronously reads off the data of the starting Json object from the Json reader,
        /// and populate the data into the memory stream.
        /// </summary>
        /// <param name="reader"> The json reader pointing at the json structure whose data needs to
        /// be populated into an memory stream.
        /// </param>
        /// <returns>A task that represents the asynchronous write operation.</returns>
        private async Task WriteJsonContentAsync(IJsonReaderAsync reader)
        {
            // Reader is on the value node after the "body" property name node.
            IJsonWriterAsync jsonWriter = new JsonWriter(
                new StreamWriter(this),
                reader.IsIeee754Compatible);

            await WriteCurrentJsonObjectAsync(reader, jsonWriter)
            .ConfigureAwait(false);

            await this.FlushAsync()
            .ConfigureAwait(false);

            this.Position = 0;
        }
예제 #15
0
        /// <summary>
        /// Asynchronously reads the json array from the reader.
        /// </summary>
        /// <param name="jsonReader">JsonReader instance.</param>
        /// <param name="inputContext">The input context with all the settings.</param>
        /// <param name="recursionDepth">The recursion depth to start with.</param>
        /// <returns>A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains a lit of JSON objects.</returns>
        /// <returns>a list of json objects.</returns>
        private static async Task <List <object> > ReadArrayValueAsync(IJsonReaderAsync jsonReader, ODataInputContext inputContext, int recursionDepth)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");
            Debug.Assert(jsonReader.NodeType == JsonNodeType.StartArray, "jsonReader.NodeType == JsonNodeType.StartArray");
            Debug.Assert(inputContext != null, "inputContext != null");

            ValidationUtils.IncreaseAndValidateRecursionDepth(ref recursionDepth, inputContext.MessageReaderSettings.MessageQuotas.MaxNestingDepth);

            List <object> items = new List <object>();
            await jsonReader.ReadNextAsync()
            .ConfigureAwait(false);

            while (jsonReader.NodeType != JsonNodeType.EndArray)
            {
                switch (jsonReader.NodeType)
                {
                case JsonNodeType.PrimitiveValue:
                    items.Add(await jsonReader.ReadPrimitiveValueAsync()
                              .ConfigureAwait(false));
                    break;

                case JsonNodeType.StartObject:
                    items.Add(await ReadObjectValueAsync(jsonReader, /*insideJsonObjectValue*/ false, inputContext, recursionDepth)
                              .ConfigureAwait(false));
                    break;

                case JsonNodeType.StartArray:
                    items.Add(await ReadArrayValueAsync(jsonReader, inputContext, recursionDepth)
                              .ConfigureAwait(false));
                    break;

                default:
                    Debug.Assert(false, "We should never have got here - the valid states in array are primitive value or object");
                    return(null);
                }
            }

            await jsonReader.ReadEndArrayAsync()
            .ConfigureAwait(false);

            return(items);
        }
예제 #16
0
        /// <summary>
        /// Asynchronously reads the next node from the <paramref name="jsonReader"/> and verifies that it is a PrimitiveValue node of type string.
        /// </summary>
        /// <param name="jsonReader">The <see cref="JsonReader"/> to read from.</param>
        /// <param name="propertyName">The name of the property for which to read the string; used in error messages only.</param>
        /// <returns>A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains the string value read from the reader;
        /// throws an exception if no string value could be read.</returns>
        internal static async Task <string> ReadStringValueAsync(this IJsonReaderAsync jsonReader, string propertyName = null)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");

            object value = await jsonReader.ReadPrimitiveValueAsync()
                           .ConfigureAwait(false);

            string stringValue = value as string;

            if (value == null || stringValue != null)
            {
                return(stringValue);
            }

            if (!string.IsNullOrEmpty(propertyName))
            {
                throw CreateException(Strings.JsonReaderExtensions_CannotReadPropertyValueAsString(value, propertyName));
            }
            else
            {
                throw CreateException(Strings.JsonReaderExtensions_CannotReadValueAsString(value));
            }
        }
예제 #17
0
        /// <summary>
        /// Asynchronously reads the json object value from the jsonReader
        /// </summary>
        /// <param name="jsonReader">Json reader to read payload from the wire.</param>
        /// <param name="insideJsonObjectValue">true if the reader is positioned on the first property of the value which is a JSON Object
        /// (or the second property if the first one was odata.type).</param>
        /// <param name="inputContext">The input context with all the settings.</param>
        /// <param name="recursionDepth">The recursion depth to start with.</param>
        /// <returns>A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains an instance of IDictionary containing the spatial value.</returns>
        private static async Task <Dictionary <string, object> > ReadObjectValueAsync(
            IJsonReaderAsync jsonReader,
            bool insideJsonObjectValue,
            ODataInputContext inputContext,
            int recursionDepth)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");
            Debug.Assert(insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject,
                         "insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject");
            Debug.Assert(
                !insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.Property || jsonReader.NodeType == JsonNodeType.EndObject,
                "!insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.Property || jsonReader.NodeType == JsonNodeType.EndObject");
            Debug.Assert(inputContext != null, "inputContext != null");

            ValidationUtils.IncreaseAndValidateRecursionDepth(ref recursionDepth, inputContext.MessageReaderSettings.MessageQuotas.MaxNestingDepth);

            Dictionary <string, object> jsonValue = new Dictionary <string, object>(StringComparer.Ordinal);

            if (!insideJsonObjectValue)
            {
                // Note that if the insideJsonObjectValue is true we will ignore the odata.type instance annotation
                // which might have been there. This is OK since for spatial we only need the normal properties anyway.
                await jsonReader.ReadNextAsync()
                .ConfigureAwait(false);
            }

            while (jsonReader.NodeType != JsonNodeType.EndObject)
            {
                // read the property name
                string propertyName = await jsonReader.ReadPropertyNameAsync()
                                      .ConfigureAwait(false);

                // read the property value
                object propertyValue;
                switch (jsonReader.NodeType)
                {
                case JsonNodeType.PrimitiveValue:
                    propertyValue = await jsonReader.ReadPrimitiveValueAsync()
                                    .ConfigureAwait(false);

                    break;

                case JsonNodeType.StartArray:
                    propertyValue = await ReadArrayValueAsync(jsonReader, inputContext, recursionDepth)
                                    .ConfigureAwait(false);

                    break;

                case JsonNodeType.StartObject:
                    propertyValue = await ReadObjectValueAsync(jsonReader, /*insideJsonObjectValue*/ false, inputContext, recursionDepth)
                                    .ConfigureAwait(false);

                    break;

                default:
                    Debug.Assert(false, "We should never reach here - There should be matching end element");
                    return(null);
                }

                jsonValue.Add(ODataAnnotationNames.RemoveAnnotationPrefix(propertyName), propertyValue);
            }

            await jsonReader.ReadEndObjectAsync()
            .ConfigureAwait(false);

            return(jsonValue);
        }
예제 #18
0
 /// <summary>
 /// Asynchronously reads the next node from the <paramref name="jsonReader"/> as a URI and verifies that it is a PrimitiveValue node of type string.
 /// </summary>
 /// <param name="jsonReader">The <see cref="JsonReader"/> to read from.</param>
 /// <returns>A task that represents the asynchronous read operation.
 /// The value of the TResult parameter contains the string value read from the reader as a URI;
 /// throws an exception if no string value could be read.</returns>
 internal static async Task <Uri> ReadUriValueAsync(this IJsonReaderAsync jsonReader)
 {
     return(UriUtils.StringToUri(await ReadStringValueAsync(jsonReader)
                                 .ConfigureAwait(false)));
 }
예제 #19
0
        /// <summary>
        /// Asynchronously skips over a JSON value (primitive, object or array), and append raw string to StringBuilder.
        /// </summary>
        /// <param name="jsonReader">The <see cref="JsonReader"/> to read from.</param>
        /// <param name="jsonRawValueStringBuilder">The StringBuilder to receive JSON raw string.</param>
        /// <returns>A task that represents the asynchronous read operation.</returns>
        internal static async Task SkipValueAsync(this IJsonReaderAsync jsonReader, StringBuilder jsonRawValueStringBuilder)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");
            using (StringWriter stringWriter = new StringWriter(jsonRawValueStringBuilder, CultureInfo.InvariantCulture))
            {
                JsonWriter jsonWriter = new JsonWriter(stringWriter, jsonReader.IsIeee754Compatible);
                int        depth      = 0;

                do
                {
                    switch (jsonReader.NodeType)
                    {
                    case JsonNodeType.PrimitiveValue:
                        if (await jsonReader.GetValueAsync().ConfigureAwait(false) == null)
                        {
                            await jsonWriter.WriteValueAsync((string)null)
                            .ConfigureAwait(false);
                        }
                        else
                        {
                            object primitiveValue = await jsonReader.GetValueAsync()
                                                    .ConfigureAwait(false);

                            await jsonWriter.WritePrimitiveValueAsync(primitiveValue)
                            .ConfigureAwait(false);
                        }

                        break;

                    case JsonNodeType.StartArray:
                        await jsonWriter.StartArrayScopeAsync()
                        .ConfigureAwait(false);

                        depth++;
                        break;

                    case JsonNodeType.StartObject:
                        await jsonWriter.StartObjectScopeAsync()
                        .ConfigureAwait(false);

                        depth++;
                        break;

                    case JsonNodeType.EndArray:
                        await jsonWriter.EndArrayScopeAsync()
                        .ConfigureAwait(false);

                        Debug.Assert(depth > 0, "Seen too many scope ends.");
                        depth--;
                        break;

                    case JsonNodeType.EndObject:
                        await jsonWriter.EndObjectScopeAsync()
                        .ConfigureAwait(false);

                        Debug.Assert(depth > 0, "Seen too many scope ends.");
                        depth--;
                        break;

                    case JsonNodeType.Property:
                        string propertyName = await jsonReader.GetPropertyNameAsync()
                                              .ConfigureAwait(false);

                        await jsonWriter.WriteNameAsync(propertyName)
                        .ConfigureAwait(false);

                        break;

                    default:
                        Debug.Assert(
                            jsonReader.NodeType != JsonNodeType.EndOfInput,
                            "We should not have reached end of input, since the scopes should be well formed. Otherwise JsonReader should have failed by now.");
                        break;
                    }
                }while (await jsonReader.ReadAsync().ConfigureAwait(false) && depth > 0);

                if (depth > 0)
                {
                    // Not all open scopes were closed:
                    // "Invalid JSON. Unexpected end of input was found in JSON content. Not all object and array scopes were closed."
                    throw CreateException(Strings.JsonReader_EndOfInputWithOpenScope);
                }

                await jsonWriter.FlushAsync()
                .ConfigureAwait(false);
            }
        }
예제 #20
0
 /// <summary>
 /// Determines if the reader is on a value node.
 /// </summary>
 /// <param name="jsonReader">The reader to inspect.</param>
 /// <returns>true if the reader is on PrimitiveValue, StartObject or StartArray node, false otherwise.</returns>
 internal static bool IsOnValueNode(this IJsonReaderAsync jsonReader)
 {
     return(IsValueNodeType(jsonReader.NodeType));
 }
예제 #21
0
        /// <summary>
        /// Asynchronously reads the next node from the <paramref name="jsonReader"/> and verifies that it is an EndArray node.
        /// </summary>
        /// <param name="jsonReader">The <see cref="JsonReader"/> to read from.</param>
        /// <returns>A task that represents the asynchronous read operation.</returns>
        internal static Task ReadEndArrayAsync(this IJsonReaderAsync jsonReader)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");

            return(ReadNextAsync(jsonReader, JsonNodeType.EndArray));
        }
        /// <summary>
        /// Asynchronously writes the current Json object.
        /// </summary>
        /// <param name="reader">The Json reader providing the data.</param>
        /// <param name="jsonWriter">The Json writer writes data into memory stream.</param>
        /// <returns>A task that represents the asynchronous write operation.</returns>
        private static async Task WriteCurrentJsonObjectAsync(IJsonReaderAsync reader, IJsonWriterAsync jsonWriter)
        {
            Stack <JsonNodeType> nodeTypes = new Stack <JsonNodeType>();

            do
            {
                switch (reader.NodeType)
                {
                case JsonNodeType.PrimitiveValue:
                    object primitiveValue;

                    if ((primitiveValue = await reader.GetValueAsync().ConfigureAwait(false)) != null)
                    {
                        await jsonWriter.WritePrimitiveValueAsync(primitiveValue)
                        .ConfigureAwait(false);
                    }
                    else
                    {
                        await jsonWriter.WriteValueAsync((string)null)
                        .ConfigureAwait(false);
                    }

                    break;

                case JsonNodeType.Property:
                    object propertyName = await reader.GetValueAsync()
                                          .ConfigureAwait(false);

                    await jsonWriter.WriteNameAsync(propertyName.ToString())
                    .ConfigureAwait(false);

                    break;

                case JsonNodeType.StartObject:
                    nodeTypes.Push(reader.NodeType);
                    await jsonWriter.StartObjectScopeAsync()
                    .ConfigureAwait(false);

                    break;

                case JsonNodeType.StartArray:
                    nodeTypes.Push(reader.NodeType);
                    await jsonWriter.StartArrayScopeAsync()
                    .ConfigureAwait(false);

                    break;

                case JsonNodeType.EndObject:
                    Debug.Assert(nodeTypes.Peek() == JsonNodeType.StartObject);
                    nodeTypes.Pop();
                    await jsonWriter.EndObjectScopeAsync()
                    .ConfigureAwait(false);

                    break;

                case JsonNodeType.EndArray:
                    Debug.Assert(nodeTypes.Peek() == JsonNodeType.StartArray);
                    nodeTypes.Pop();
                    await jsonWriter.EndArrayScopeAsync()
                    .ConfigureAwait(false);

                    break;

                default:
                    throw new ODataException(Strings.ODataJsonLightBatchBodyContentReaderStream_UnexpectedNodeType(reader.NodeType));
                }

                await reader.ReadNextAsync()
                .ConfigureAwait(false);     // This can be EndOfInput, where nodeTypes should be empty.
            }while (nodeTypes.Count != 0);

            await jsonWriter.FlushAsync()
            .ConfigureAwait(false);
        }
예제 #23
0
        /// <summary>
        /// Asynchronously reads the next node from the <paramref name="jsonReader"/> as an <see cref="ODataValue"/>.
        /// </summary>
        /// <param name="jsonReader">The reader to inspect.</param>
        /// <returns>A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains the <see cref="ODataValue"/> value read from the reader.</returns>
        internal static async Task <ODataValue> ReadODataValueAsync(this IJsonReaderAsync jsonReader)
        {
            if (jsonReader.NodeType == JsonNodeType.PrimitiveValue)
            {
                object primitiveValue = await jsonReader.ReadPrimitiveValueAsync()
                                        .ConfigureAwait(false);

                return(primitiveValue.ToODataValue());
            }
            else if (jsonReader.NodeType == JsonNodeType.StartObject)
            {
                await jsonReader.ReadStartObjectAsync()
                .ConfigureAwait(false);

                ODataResourceValue   resourceValue = new ODataResourceValue();
                List <ODataProperty> properties    = new List <ODataProperty>();

                while (jsonReader.NodeType != JsonNodeType.EndObject)
                {
                    ODataProperty property = new ODataProperty();
                    property.Name = await jsonReader.ReadPropertyNameAsync()
                                    .ConfigureAwait(false);

                    property.Value = await jsonReader.ReadODataValueAsync()
                                     .ConfigureAwait(false);

                    properties.Add(property);
                }

                resourceValue.Properties = properties;

                await jsonReader.ReadEndObjectAsync()
                .ConfigureAwait(false);

                return(resourceValue);
            }
            else if (jsonReader.NodeType == JsonNodeType.StartArray)
            {
                await jsonReader.ReadStartArrayAsync()
                .ConfigureAwait(false);

                ODataCollectionValue collectionValue = new ODataCollectionValue();
                List <object>        properties      = new List <object>();

                while (jsonReader.NodeType != JsonNodeType.EndArray)
                {
                    ODataValue odataValue = await jsonReader.ReadODataValueAsync()
                                            .ConfigureAwait(false);

                    properties.Add(odataValue);
                }

                collectionValue.Items = properties;
                await jsonReader.ReadEndArrayAsync()
                .ConfigureAwait(false);

                return(collectionValue);
            }
            else
            {
                return(await jsonReader.ReadAsUntypedOrNullValueAsync()
                       .ConfigureAwait(false));
            }
        }
예제 #24
0
        /// <summary>
        /// Wrapper method with validation to asynchronously scan the JSON object for known properties.
        /// </summary>
        /// <returns>A task that represents the asynchronous read operation.</returns>
        private async Task ScanJsonPropertiesAsync()
        {
            Debug.Assert(this.asynchronousJsonReader != null, $"{nameof(this.asynchronousJsonReader)} != null");
            Debug.Assert(this.jsonProperties == null, $"{nameof(this.jsonProperties)} == null");

            this.jsonProperties = new Dictionary <string, object>();
            string contentTypeHeader = null;
            ODataJsonLightBatchBodyContentReaderStream bodyContentStream = null;

            try
            {
                // Request object start.
                await this.asynchronousJsonReader.ReadStartObjectAsync()
                .ConfigureAwait(false);

                while (this.asynchronousJsonReader.NodeType != JsonNodeType.EndObject)
                {
                    // Convert to upper case to support case-insensitive request property names
                    string propertyName = Normalize(await this.asynchronousJsonReader.ReadPropertyNameAsync().ConfigureAwait(false));

                    switch (propertyName)
                    {
                    case PropertyNameId:
                    case PropertyNameAtomicityGroup:
                    case PropertyNameMethod:
                    case PropertyNameUrl:
                        jsonProperties.Add(
                            propertyName,
                            await this.asynchronousJsonReader.ReadStringValueAsync().ConfigureAwait(false));

                        break;

                    case PropertyNameStatus:
                        jsonProperties.Add(
                            propertyName,
                            await this.asynchronousJsonReader.ReadPrimitiveValueAsync().ConfigureAwait(false));

                        break;

                    case PropertyNameDependsOn:
                        List <string> dependsOnIds = new List <string>();
                        await this.asynchronousJsonReader.ReadStartArrayAsync()
                        .ConfigureAwait(false);

                        while (this.asynchronousJsonReader.NodeType != JsonNodeType.EndArray)
                        {
                            dependsOnIds.Add(await this.asynchronousJsonReader.ReadStringValueAsync().ConfigureAwait(false));
                        }

                        await this.asynchronousJsonReader.ReadEndArrayAsync()
                        .ConfigureAwait(false);

                        jsonProperties.Add(propertyName, dependsOnIds);

                        break;

                    case PropertyNameHeaders:
                        ODataBatchOperationHeaders headers = new ODataBatchOperationHeaders();

                        // Use empty string (non-null value) to indicate that content-type header has been processed.
                        contentTypeHeader = "";

                        await this.asynchronousJsonReader.ReadStartObjectAsync()
                        .ConfigureAwait(false);

                        while (this.asynchronousJsonReader.NodeType != JsonNodeType.EndObject)
                        {
                            string headerName = await this.asynchronousJsonReader.ReadPropertyNameAsync()
                                                .ConfigureAwait(false);

                            string headerValue = (await this.asynchronousJsonReader.ReadPrimitiveValueAsync().ConfigureAwait(false)).ToString();

                            // Remember the Content-Type header value.
                            if (headerName.Equals(ODataConstants.ContentTypeHeader, StringComparison.OrdinalIgnoreCase))
                            {
                                contentTypeHeader = headerValue;
                            }

                            headers.Add(headerName, headerValue);
                        }

                        await this.asynchronousJsonReader.ReadEndObjectAsync()
                        .ConfigureAwait(false);

                        jsonProperties.Add(propertyName, headers);

                        if (!this.isStreamPopulated && bodyContentStream != null)
                        {
                            // Populate the stream now since the body content has been cached and we now have content-type.
                            await bodyContentStream.PopulateCachedBodyContentAsync(contentTypeHeader)
                            .ConfigureAwait(false);
                        }

                        break;

                    case PropertyNameBody:
                        bodyContentStream = await CreateJsonPayloadBodyContentStreamAsync(contentTypeHeader)
                                            .ConfigureAwait(false);

                        jsonProperties.Add(propertyName, bodyContentStream);

                        break;

                    default:
                        throw new ODataException(Strings.ODataJsonLightBatchPayloadItemPropertiesCache_UnknownPropertyForMessageInBatch(propertyName));
                    }
                }

                // Request object end.
                await this.asynchronousJsonReader.ReadEndObjectAsync()
                .ConfigureAwait(false);
            }
            finally
            {
                // We don't need to use the Json reader anymore.
                this.asynchronousJsonReader = null;
            }
        }
예제 #25
0
        /// <summary>
        /// Asynchronously reads the next node from the <paramref name="jsonReader"/> and verifies that it is a StartObject node.
        /// </summary>
        /// <param name="jsonReader">The <see cref="JsonReader"/> to read from.</param>
        /// <returns>A task that represents the asynchronous read operation.</returns>
        internal static Task ReadStartObjectAsync(this IJsonReaderAsync jsonReader)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");

            return(ReadNextAsync(jsonReader, JsonNodeType.StartObject));
        }