/// <summary> /// Asynchronously writes the json value (primitive, IDictionary or IEnumerable) to the underlying json writer. /// </summary> /// <param name="jsonWriter">The <see cref="JsonWriter"/> to write to.</param> /// <param name="propertyValue">value to write.</param> /// <returns>A task that represents the asynchronous write operation.</returns> private static async Task WriteJsonValueAsync(this IJsonWriterAsync jsonWriter, object propertyValue) { if (propertyValue == null) { await jsonWriter.WriteValueAsync((string)null).ConfigureAwait(false); } else if (EdmLibraryExtensions.IsPrimitiveType(propertyValue.GetType())) { await jsonWriter.WritePrimitiveValueAsync(propertyValue).ConfigureAwait(false); } else { IDictionary <string, object> objectValue = propertyValue as IDictionary <string, object>; if (objectValue != null) { await jsonWriter.WriteJsonObjectValueAsync(objectValue, null /*typeName */).ConfigureAwait(false); } else { IEnumerable arrayValue = propertyValue as IEnumerable; Debug.Assert(arrayValue != null, "arrayValue != null"); await jsonWriter.WriteJsonArrayValueAsync(arrayValue).ConfigureAwait(false); } } }
private async Task VerifyWriterPrimitiveValueWithIeee754CompatibleAsync <T>(T parameter, string expected, bool isIeee754Compatible) { this.writer = new JsonWriter(new StringWriter(builder), isIeee754Compatible); await this.writer.WritePrimitiveValueAsync(parameter); Assert.Equal(expected, this.builder.ToString()); }
public ODataJsonWriterUtilsAsyncTests() { this.stringWriter = new StringWriter(); this.jsonWriter = new JsonWriter(this.stringWriter, isIeee754Compatible: true); this.settings = new ODataMessageWriterSettings(); this.writeInstanceAnnotationsDelegate = async(ICollection <ODataInstanceAnnotation> instanceAnnotations) => await TaskUtils.CompletedTask; }
/// <summary> /// Write a JSON instance annotation name which represents a instance annotation. /// </summary> /// <param name="jsonWriter">The JSON writer to write to.</param> /// <param name="annotationName">The name of the instance annotation to write.</param> internal static Task WriteInstanceAnnotationNameAsync(this IJsonWriterAsync jsonWriter, string annotationName) { Debug.Assert(jsonWriter != null, "jsonWriter != null"); Debug.Assert(!string.IsNullOrEmpty(annotationName), "!string.IsNullOrEmpty(annotationName)"); return(jsonWriter.WriteNameAsync(JsonLightConstants.ODataPropertyAnnotationSeparatorChar + annotationName)); }
/// <summary> /// Asynchronously writes an error message. /// </summary> /// <param name="jsonWriter">The JSON writer to write the error.</param> /// <param name="writeInstanceAnnotationsDelegate">Delegate to write the instance annotations.</param> /// <param name="error">The error instance to write.</param> /// <param name="includeDebugInformation">A flag indicating whether error details should be written (in debug mode only) or not.</param> /// <param name="maxInnerErrorDepth">The maximum number of nested inner errors to allow.</param> /// <returns>A task that represents the asynchronous write operation.</returns> internal static Task WriteErrorAsync( IJsonWriterAsync jsonWriter, Func <ICollection <ODataInstanceAnnotation>, Task> writeInstanceAnnotationsDelegate, ODataError error, bool includeDebugInformation, int maxInnerErrorDepth) { Debug.Assert(jsonWriter != null, "jsonWriter != null"); Debug.Assert(error != null, "error != null"); ExceptionUtils.CheckArgumentNotNull(writeInstanceAnnotationsDelegate, "writeInstanceAnnotationsDelegate"); string code, message; ErrorUtils.GetErrorDetails(error, out code, out message); ODataInnerError innerError = includeDebugInformation ? error.InnerError : null; return(WriteErrorAsync( jsonWriter, code, message, error.Target, error.Details, innerError, error.GetInstanceAnnotations(), writeInstanceAnnotationsDelegate, maxInnerErrorDepth)); }
public ODataJsonLightWriterUtilsTests() { this.builder = new StringBuilder(); this.stringWriter = new StringWriter(builder); this.jsonWriter = new JsonWriter(this.stringWriter, isIeee754Compatible: true); this.asyncJsonWriter = new JsonWriter(this.stringWriter, isIeee754Compatible: true); }
/// <summary> /// Constructor. /// </summary> /// <param name="jsonWriter">The underlying JSON writer.</param> /// <param name="enableWritingODataAnnotationWithoutPrefix">Whether write odata annotation without "odata." prefix in name.</param> /// <param name="odataVersion">OData Version used when writing the annotations.</param> public JsonLightODataAnnotationWriter(IJsonWriterAsync asyncJsonWriter, bool enableWritingODataAnnotationWithoutPrefix, ODataVersion?odataVersion) { Debug.Assert(asyncJsonWriter != null, "asyncJsonWriter != null"); this.asyncJsonWriter = asyncJsonWriter; this.enableWritingODataAnnotationWithoutPrefix = enableWritingODataAnnotationWithoutPrefix; this.odataVersion = odataVersion ?? ODataVersion.V4; }
public JsonLightODataAnnotationWriterTests() { this.builder = new StringBuilder(); this.stringWriter = new StringWriter(builder); this.asyncJsonWriter = (IJsonWriterAsync) new JsonWriter(this.stringWriter, isIeee754Compatible: true); this.asyncODataAnnotationWriter = new JsonLightODataAnnotationWriter( this.asyncJsonWriter, false, ODataVersion.V4); }
/// <summary> /// If we are writing a response and the given Json Padding function name is not null or empty /// this function will close the JSONP scope asynchronously. /// </summary> /// <param name="jsonWriter">JsonWriter to write to.</param> /// <param name="settings">Writer settings.</param> /// <returns>A task that represents the asynchronous operation.</returns> internal static Task EndJsonPaddingIfRequiredAsync(IJsonWriterAsync jsonWriter, ODataMessageWriterSettings settings) { Debug.Assert(jsonWriter != null, "jsonWriter should not be null"); if (settings.HasJsonPaddingFunction()) { return(jsonWriter.EndPaddingFunctionScopeAsync()); } return(TaskUtils.CompletedTask); }
/// <summary> /// Constructs a <see cref="JsonLightInstanceAnnotationWriter"/> that can write a collection of <see cref="ODataInstanceAnnotation"/>. /// </summary> /// <param name="valueSerializer">The <see cref="ODataJsonLightValueSerializer"/> to use for writing values of instance annotations. /// The <see cref="IJsonWriter"/> that is also used internally will be acquired from the this instance.</param> /// <param name="typeNameOracle">The oracle to use to determine the type name to write for entries and values.</param> internal JsonLightInstanceAnnotationWriter(ODataJsonLightValueSerializer valueSerializer, JsonLightTypeNameOracle typeNameOracle) { Debug.Assert(valueSerializer != null, "valueSerializer should not be null"); this.valueSerializer = valueSerializer; this.typeNameOracle = typeNameOracle; this.jsonWriter = this.valueSerializer.JsonWriter; this.odataAnnotationWriter = this.valueSerializer.ODataAnnotationWriter; this.asynchronousJsonWriter = this.valueSerializer.AsynchronousJsonWriter; this.asynchronousODataAnnotationWriter = this.valueSerializer.AsynchronousODataAnnotationWriter; this.writerValidator = this.valueSerializer.MessageWriterSettings.Validator; }
/// <summary> /// Asynchronously writes the function's name and start the JSONP scope if we are writing a response and the /// JSONP function name is not null or empty. /// </summary> /// <param name="jsonWriter">JsonWriter to write to.</param> /// <param name="settings">Writer settings.</param> /// <returns>A task that represents the asynchronous operation.</returns> internal static async Task StartJsonPaddingIfRequiredAsync(IJsonWriterAsync jsonWriter, ODataMessageWriterSettings settings) { Debug.Assert(jsonWriter != null, "jsonWriter should not be null"); if (settings.HasJsonPaddingFunction()) { await jsonWriter.WritePaddingFunctionNameAsync(settings.JsonPCallback).ConfigureAwait(false); await jsonWriter.StartPaddingFunctionScopeAsync().ConfigureAwait(false); } }
/// <summary> /// Asynchronously writes the json array value. /// </summary> /// <param name="jsonWriter">The <see cref="JsonWriter"/> to write to.</param> /// <param name="arrayValue">Writes the json array value to the underlying json writer.</param> /// <returns>A task that represents the asynchronous write operation.</returns> private static async Task WriteJsonArrayValueAsync(this IJsonWriterAsync jsonWriter, IEnumerable arrayValue) { Debug.Assert(arrayValue != null, "arrayValue != null"); await jsonWriter.StartArrayScopeAsync().ConfigureAwait(false); foreach (object element in arrayValue) { await jsonWriter.WriteJsonValueAsync(element).ConfigureAwait(false); } await jsonWriter.EndArrayScopeAsync().ConfigureAwait(false); }
/// <summary> /// Write an inner error property and message. /// </summary> /// <param name="jsonWriter">The JSON writer to write the error to.</param> /// <param name="innerError">Inner error details.</param> /// <param name="innerErrorPropertyName">The property name for the inner error property.</param> /// <param name="recursionDepth">The number of times this method has been called recursively.</param> /// <param name="maxInnerErrorDepth">The maximum number of nested inner errors to allow.</param> /// <returns>A task that represents the asynchronous write operation.</returns> private static async Task WriteInnerErrorAsync(IJsonWriterAsync jsonWriter, ODataInnerError innerError, string innerErrorPropertyName, int recursionDepth, int maxInnerErrorDepth) { Debug.Assert(jsonWriter != null, "jsonWriter != null"); Debug.Assert(innerErrorPropertyName != null, "innerErrorPropertyName != null"); ValidationUtils.IncreaseAndValidateRecursionDepth(ref recursionDepth, maxInnerErrorDepth); // "innererror": await jsonWriter.WriteNameAsync(innerErrorPropertyName).ConfigureAwait(false); await jsonWriter.StartObjectScopeAsync().ConfigureAwait(false); if (innerError.Properties != null) { foreach (KeyValuePair <string, ODataValue> pair in innerError.Properties) { await jsonWriter.WriteNameAsync(pair.Key).ConfigureAwait(false); if (pair.Value is ODataNullValue && (pair.Key == JsonConstants.ODataErrorInnerErrorMessageName || pair.Key == JsonConstants.ODataErrorInnerErrorStackTraceName || pair.Key == JsonConstants.ODataErrorInnerErrorTypeNameName)) { // Write empty string for null values in stacktrace, type and message properties of inner error. await jsonWriter.WriteODataValueAsync(new ODataPrimitiveValue(string.Empty)).ConfigureAwait(false); } else { await jsonWriter.WriteODataValueAsync(pair.Value).ConfigureAwait(false); } } } if (innerError.InnerError != null) { // "internalexception": { <nested inner error> } await WriteInnerErrorAsync(jsonWriter, innerError.InnerError, JsonConstants.ODataErrorInnerErrorInnerErrorName, recursionDepth, maxInnerErrorDepth).ConfigureAwait(false); } // } await jsonWriter.EndObjectScopeAsync().ConfigureAwait(false); }
/// <summary> /// Asynchronously writes the error details. /// </summary> /// <param name="jsonWriter">JSON writer.</param> /// <param name="details">The details of the error.</param> /// <param name="odataErrorDetailsName">The property name for the error details property.</param> /// <returns>A task that represents the asynchronous write operation.</returns> private static async Task WriteErrorDetailsAsync(IJsonWriterAsync jsonWriter, IEnumerable <ODataErrorDetail> details, string odataErrorDetailsName) { Debug.Assert(jsonWriter != null, "jsonWriter != null"); Debug.Assert(details != null, "details != null"); Debug.Assert(odataErrorDetailsName != null, "odataErrorDetailsName != null"); // "details": [ await jsonWriter.WriteNameAsync(odataErrorDetailsName).ConfigureAwait(false); await jsonWriter.StartArrayScopeAsync().ConfigureAwait(false); foreach (var detail in details.Where(d => d != null)) { // { await jsonWriter.StartObjectScopeAsync().ConfigureAwait(false); // "code": "301", await jsonWriter.WriteNameAsync(JsonConstants.ODataErrorCodeName).ConfigureAwait(false); await jsonWriter.WriteValueAsync(detail.ErrorCode ?? string.Empty).ConfigureAwait(false); if (detail.Target != null) { // "target": "$search" await jsonWriter.WriteNameAsync(JsonConstants.ODataErrorTargetName).ConfigureAwait(false); await jsonWriter.WriteValueAsync(detail.Target).ConfigureAwait(false); } // "message": "$search query option not supported", await jsonWriter.WriteNameAsync(JsonConstants.ODataErrorMessageName).ConfigureAwait(false); await jsonWriter.WriteValueAsync(detail.Message ?? string.Empty).ConfigureAwait(false); // } await jsonWriter.EndObjectScopeAsync().ConfigureAwait(false); } // ] await jsonWriter.EndArrayScopeAsync().ConfigureAwait(false); }
/// <summary> /// Asynchronously writes the json object value to the <paramref name="jsonWriter"/>. /// </summary> /// <param name="jsonWriter">The <see cref="JsonWriter"/> to write to.</param> /// <param name="jsonObjectValue">Writes the given json object value to the underlying json writer.</param> /// <param name="injectPropertyDelegate">Called when the top-level object is started to possibly inject first property into the object.</param> /// <returns>A task that represents the asynchronous write operation.</returns> internal static async Task WriteJsonObjectValueAsync( this IJsonWriterAsync jsonWriter, IDictionary <string, object> jsonObjectValue, Func <IJsonWriterAsync, Task> injectPropertyDelegate) { Debug.Assert(jsonWriter != null, "jsonWriter != null"); Debug.Assert(jsonObjectValue != null, "jsonObjectValue != null"); await jsonWriter.StartObjectScopeAsync().ConfigureAwait(false); if (injectPropertyDelegate != null) { await injectPropertyDelegate(jsonWriter).ConfigureAwait(false); } foreach (KeyValuePair <string, object> property in jsonObjectValue) { await jsonWriter.WriteNameAsync(property.Key).ConfigureAwait(false); await jsonWriter.WriteJsonValueAsync(property.Value).ConfigureAwait(false); } await jsonWriter.EndObjectScopeAsync().ConfigureAwait(false); }
/// <summary> /// Asynchronously writes the ODataValue (primitive, collection or resource value) to the underlying json writer. /// </summary> /// <param name="jsonWriter">The <see cref="JsonWriter"/> to write to.</param> /// <param name="odataValue">value to write.</param> /// <returns>A task that represents the asynchronous write operation.</returns> internal static async Task WriteODataValueAsync(this IJsonWriterAsync jsonWriter, ODataValue odataValue) { if (odataValue == null || odataValue is ODataNullValue) { await jsonWriter.WriteValueAsync((string)null).ConfigureAwait(false); return; } object objectValue = odataValue.FromODataValue(); if (EdmLibraryExtensions.IsPrimitiveType(objectValue.GetType())) { await jsonWriter.WritePrimitiveValueAsync(objectValue).ConfigureAwait(false); return; } ODataResourceValue resourceValue = odataValue as ODataResourceValue; if (resourceValue != null) { await jsonWriter.StartObjectScopeAsync().ConfigureAwait(false); foreach (ODataProperty property in resourceValue.Properties) { await jsonWriter.WriteNameAsync(property.Name).ConfigureAwait(false); await jsonWriter.WriteODataValueAsync(property.ODataValue).ConfigureAwait(false); } await jsonWriter.EndObjectScopeAsync().ConfigureAwait(false); return; } ODataCollectionValue collectionValue = odataValue as ODataCollectionValue; if (collectionValue != null) { await jsonWriter.StartArrayScopeAsync().ConfigureAwait(false); foreach (object item in collectionValue.Items) { // Will not be able to accurately serialize complex objects unless they are ODataValues. ODataValue collectionItem = item as ODataValue; if (item != null) { await jsonWriter.WriteODataValueAsync(collectionItem).ConfigureAwait(false); } else { throw new ODataException(ODataErrorStrings.ODataJsonWriter_UnsupportedValueInCollection); } } await jsonWriter.EndArrayScopeAsync().ConfigureAwait(false); return; } throw new ODataException( ODataErrorStrings.ODataJsonWriter_UnsupportedValueType(odataValue.GetType().FullName)); }
/// <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); }
/// <summary> /// Writes the 'value' property name asynchronously. /// </summary> /// <param name="jsonWriter">The JSON writer to write to.</param> internal static Task WriteValuePropertyNameAsync(this IJsonWriterAsync jsonWriter) { Debug.Assert(jsonWriter != null, "jsonWriter != null"); return(jsonWriter.WriteNameAsync(JsonLightConstants.ODataValuePropertyName)); }
public JsonWriterAsyncTests() { this.builder = new StringBuilder(); this.writer = new JsonWriter(new StringWriter(builder), isIeee754Compatible: true); }
/// <summary> /// Asynchronously writes a primitive value. /// </summary> /// <param name="jsonWriter">The <see cref="JsonWriter"/> to write to.</param> /// <param name="value">The value to write.</param> /// <returns>A task that represents the asynchronous write operation.</returns> internal static async Task WritePrimitiveValueAsync(this IJsonWriterAsync jsonWriter, object value) { if (value is bool) { await jsonWriter.WriteValueAsync((bool)value).ConfigureAwait(false); return; } if (value is byte) { await jsonWriter.WriteValueAsync((byte)value).ConfigureAwait(false); return; } if (value is decimal) { await jsonWriter.WriteValueAsync((decimal)value).ConfigureAwait(false); return; } if (value is double) { await jsonWriter.WriteValueAsync((double)value).ConfigureAwait(false); return; } if (value is Int16) { await jsonWriter.WriteValueAsync((Int16)value).ConfigureAwait(false); return; } if (value is Int32) { await jsonWriter.WriteValueAsync((Int32)value).ConfigureAwait(false); return; } if (value is Int64) { await jsonWriter.WriteValueAsync((Int64)value).ConfigureAwait(false); return; } if (value is sbyte) { await jsonWriter.WriteValueAsync((sbyte)value).ConfigureAwait(false); return; } if (value is Single) { await jsonWriter.WriteValueAsync((Single)value).ConfigureAwait(false); return; } var str = value as string; if (str != null) { await jsonWriter.WriteValueAsync(str).ConfigureAwait(false); return; } byte[] valueAsByteArray = value as byte[]; if (valueAsByteArray != null) { await jsonWriter.WriteValueAsync(valueAsByteArray).ConfigureAwait(false); return; } if (value is DateTimeOffset) { await jsonWriter.WriteValueAsync((DateTimeOffset)value).ConfigureAwait(false); return; } if (value is Guid) { await jsonWriter.WriteValueAsync((Guid)value).ConfigureAwait(false); return; } if (value is TimeSpan) { await jsonWriter.WriteValueAsync((TimeSpan)value).ConfigureAwait(false); return; } if (value is Date) { await jsonWriter.WriteValueAsync((Date)value).ConfigureAwait(false); return; } if (value is TimeOfDay) { await jsonWriter.WriteValueAsync((TimeOfDay)value).ConfigureAwait(false); return; } throw new ODataException(ODataErrorStrings.ODataJsonWriter_UnsupportedValueType(value.GetType().FullName)); }
/// <summary> /// Asynchronously writes an error message. /// </summary> /// <param name="jsonWriter">JSON writer.</param> /// <param name="code">The code of the error.</param> /// <param name="message">The message of the error.</param> /// <param name="target">The target of the error.</param> /// <param name="details">The details of the error.</param> /// <param name="innerError">Inner error details that will be included in debug mode (if present).</param> /// <param name="instanceAnnotations">Instance annotations for this error.</param> /// <param name="writeInstanceAnnotationsDelegate">Delegate to write the instance annotations.</param> /// <param name="maxInnerErrorDepth">The maximum number of nested inner errors to allow.</param> /// <returns>A task that represents the asynchronous write operation.</returns> private static async Task WriteErrorAsync( IJsonWriterAsync jsonWriter, string code, string message, string target, IEnumerable <ODataErrorDetail> details, ODataInnerError innerError, ICollection <ODataInstanceAnnotation> instanceAnnotations, Func <ICollection <ODataInstanceAnnotation>, Task> writeInstanceAnnotationsDelegate, int maxInnerErrorDepth) { Debug.Assert(jsonWriter != null, "jsonWriter != null"); Debug.Assert(code != null, "code != null"); Debug.Assert(message != null, "message != null"); Debug.Assert(instanceAnnotations != null, "instanceAnnotations != null"); ExceptionUtils.CheckArgumentNotNull(writeInstanceAnnotationsDelegate, "writeInstanceAnnotationsDelegate"); // "error": { await jsonWriter.StartObjectScopeAsync().ConfigureAwait(false); await jsonWriter.WriteNameAsync(JsonLightConstants.ODataErrorPropertyName).ConfigureAwait(false); await jsonWriter.StartObjectScopeAsync().ConfigureAwait(false); // "code": "<code>" await jsonWriter.WriteNameAsync(JsonConstants.ODataErrorCodeName).ConfigureAwait(false); await jsonWriter.WriteValueAsync(code).ConfigureAwait(false); // "message": "<message string>" await jsonWriter.WriteNameAsync(JsonConstants.ODataErrorMessageName).ConfigureAwait(false); await jsonWriter.WriteValueAsync(message).ConfigureAwait(false); // For example, "target": "query", if (target != null) { await jsonWriter.WriteNameAsync(JsonConstants.ODataErrorTargetName).ConfigureAwait(false); await jsonWriter.WriteValueAsync(target).ConfigureAwait(false); } // Such as, "details": [ // { // "code": "301", // "target": "$search", // "message": "$search query option not supported" // }] if (details != null) { await WriteErrorDetailsAsync(jsonWriter, details, JsonConstants.ODataErrorDetailsName).ConfigureAwait(false); } if (innerError != null) { await WriteInnerErrorAsync(jsonWriter, innerError, JsonConstants.ODataErrorInnerErrorName, /* recursionDepth */ 0, maxInnerErrorDepth).ConfigureAwait(false); } await writeInstanceAnnotationsDelegate(instanceAnnotations).ConfigureAwait(false); // } } await jsonWriter.EndObjectScopeAsync().ConfigureAwait(false); await jsonWriter.EndObjectScopeAsync().ConfigureAwait(false); }