private void VerifyDateValueReader(string payload, string edmTypeName, object expectedResult)
        {
            IEdmModel model = new EdmModel();
            IEdmPrimitiveTypeReference typeReference = new EdmPrimitiveTypeReference((IEdmPrimitiveType)model.FindType(edmTypeName), true);

            MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(payload));
            object       actualValue;

            using (ODataJsonLightInputContext inputContext = new ODataJsonLightInputContext(
                       ODataFormat.Json,
                       stream,
                       JsonLightUtils.JsonLightStreamingMediaType,
                       Encoding.UTF8,
                       new ODataMessageReaderSettings(),
                       /*readingResponse*/ true,
                       /*synchronous*/ true,
                       model,
                       /*urlResolver*/ null))
            {
                ODataJsonLightPropertyAndValueDeserializer deserializer = new ODataJsonLightPropertyAndValueDeserializer(inputContext);
                deserializer.JsonReader.Read();
                actualValue = deserializer.ReadNonEntityValue(
                    /*payloadTypeName*/ null,
                    typeReference,
                    /*duplicatePropertyNamesChecker*/ null,
                    /*collectionValidator*/ null,
                    /*validateNullValue*/ true,
                    /*isTopLevelPropertyValue*/ true,
                    /*insideComplexValue*/ false,
                    /*propertyName*/ null);
            }
            actualValue.Should().Be(expectedResult, "payload ->{0}<- for type '{1}'", payload, edmTypeName);
        }
示例#2
0
        private void VerifyDateValueReader(string payload, string edmTypeName, object expectedResult)
        {
            IEdmModel model = new EdmModel();
            IEdmPrimitiveTypeReference typeReference = new EdmPrimitiveTypeReference((IEdmPrimitiveType)model.FindType(edmTypeName), true);

            var messageInfo = new ODataMessageInfo
            {
                IsResponse = true,
                MediaType  = JsonLightUtils.JsonLightStreamingMediaType,
                IsAsync    = false,
                Model      = new EdmModel(),
            };

            object actualValue;

            using (var inputContext = new ODataJsonLightInputContext(
                       new StringReader(payload), messageInfo, new ODataMessageReaderSettings()))
            {
                var deserializer = new ODataJsonLightPropertyAndValueDeserializer(inputContext);
                deserializer.JsonReader.Read();
                actualValue = deserializer.ReadNonEntityValue(
                    /*payloadTypeName*/ null,
                    typeReference,
                    /*propertyAndAnnotationCollector*/ null,
                    /*collectionValidator*/ null,
                    /*validateNullValue*/ true,
                    /*isTopLevelPropertyValue*/ true,
                    /*insideResourceValue*/ false,
                    /*propertyName*/ null);
            }
            actualValue.Should().Be(expectedResult, "payload ->{0}<- for type '{1}'", payload, edmTypeName);
        }
        /// <summary>
        /// Reads a property value which occurs in the "error" object scope.
        /// </summary>
        /// <param name="error">The <see cref="ODataError"/> object to update with the data from this property value.</param>
        /// <param name="propertyName">The name of the property whose value is to be read.</param>
        /// <param name="duplicationPropertyNameChecker">DuplicatePropertyNamesChecker to use for extracting property annotations
        /// targetting any custom instance annotations on the error.</param>
        /// <remarks>
        /// Pre-Condition:  any                         - The value of the property being read.
        /// Post-Condition: JsonNodeType.Property       - The property after the one being read.
        ///                 JsonNodeType.EndObject      - The end of the "error" object.
        ///                 any                         - Anything else after the property value is an invalid payload (but won't fail in this method).
        /// </remarks>
        private void ReadPropertyValueInODataErrorObject(ODataError error, string propertyName, DuplicatePropertyNamesChecker duplicationPropertyNameChecker)
        {
            switch (propertyName)
            {
            case JsonConstants.ODataErrorCodeName:
                error.ErrorCode = this.JsonReader.ReadStringValue(JsonConstants.ODataErrorCodeName);
                break;

            case JsonConstants.ODataErrorMessageName:
                error.Message = this.JsonReader.ReadStringValue(JsonConstants.ODataErrorMessageName);
                break;

            case JsonConstants.ODataErrorTargetName:
                error.Target = this.JsonReader.ReadStringValue(JsonConstants.ODataErrorTargetName);
                break;

            case JsonConstants.ODataErrorDetailsName:
                error.Details = this.ReadDetails();
                break;

            case JsonConstants.ODataErrorInnerErrorName:
                error.InnerError = this.ReadInnerError(0 /* recursionDepth */);
                break;

            default:
                // See if it's an instance annotation
                if (ODataJsonLightReaderUtils.IsAnnotationProperty(propertyName))
                {
                    ODataJsonLightPropertyAndValueDeserializer valueDeserializer = new ODataJsonLightPropertyAndValueDeserializer(this.JsonLightInputContext);
                    object typeName = null;

                    var odataAnnotations = duplicationPropertyNameChecker.GetODataPropertyAnnotations(propertyName);
                    if (odataAnnotations != null)
                    {
                        odataAnnotations.TryGetValue(ODataAnnotationNames.ODataType, out typeName);
                    }

                    var value = valueDeserializer.ReadNonEntityValue(
                        typeName as string,
                        null /*expectedValueTypeReference*/,
                        null /*duplicatePropertiesNamesChecker*/,
                        null /*collectionValidator*/,
                        false /*validateNullValue*/,
                        false /*isTopLevelPropertyValue*/,
                        false /*insideComplexValue*/,
                        propertyName);

                    error.GetInstanceAnnotations().Add(new ODataInstanceAnnotation(propertyName, value.ToODataValue()));
                }
                else
                {
                    // we only allow a 'code', 'message', 'target', 'details, and 'innererror' properties
                    // in the value of the 'error' property or custom instance annotations
                    throw new ODataException(Strings.ODataJsonLightErrorDeserializer_TopLevelErrorValueWithInvalidProperty(propertyName));
                }

                break;
            }
        }
        private object WriteThenReadValue(object clrValue, IEdmTypeReference typeReference, ODataVersion version, bool isIeee754Compatible)
        {
            MemoryStream stream = new MemoryStream();

            ODataMessageWriterSettings settings = new ODataMessageWriterSettings {
                Version = version
            };

            settings.SetServiceDocumentUri(new Uri("http://odata.org/test/"));

            ODataMediaType mediaType = isIeee754Compatible
                ? new ODataMediaType("application", "json", new KeyValuePair <string, string>("IEEE754Compatible", "true"))
                : new ODataMediaType("application", "json");

            using (ODataJsonLightOutputContext outputContext = new ODataJsonLightOutputContext(
                       ODataFormat.Json,
                       new NonDisposingStream(stream),
                       mediaType,
                       Encoding.UTF8,
                       settings,
                       /*writingResponse*/ true,
                       /*synchronous*/ true,
                       this.model,
                       /*urlResolver*/ null))
            {
                ODataJsonLightValueSerializer serializer = new ODataJsonLightValueSerializer(outputContext);
                serializer.WritePrimitiveValue(clrValue, typeReference);
            }

            stream.Position = 0;

            object actualValue;

            using (ODataJsonLightInputContext inputContext = new ODataJsonLightInputContext(
                       ODataFormat.Json,
                       stream,
                       mediaType,
                       Encoding.UTF8,
                       new ODataMessageReaderSettings(),
                       /*readingResponse*/ true,
                       /*synchronous*/ true,
                       this.model,
                       /*urlResolver*/ null))
            {
                ODataJsonLightPropertyAndValueDeserializer deserializer = new ODataJsonLightPropertyAndValueDeserializer(inputContext);
                deserializer.JsonReader.Read();
                actualValue = deserializer.ReadNonEntityValue(
                    /*payloadTypeName*/ null,
                    typeReference,
                    /*duplicatePropertyNamesChecker*/ null,
                    /*collectionValidator*/ null,
                    /*validateNullValue*/ true,
                    /*isTopLevel*/ true,
                    /*insideComplexValue*/ false,
                    /*propertyName*/ null);
            }

            return(actualValue);
        }
        /// <summary>
        /// Asynchronously read the property from the input and
        /// return an <see cref="ODataProperty"/> representing the read property.
        /// </summary>
        /// <param name="property">The <see cref="IEdmProperty"/> producing the property to be read.</param>
        /// <param name="expectedPropertyTypeReference">The expected type reference of the property to read.</param>
        /// <returns>Task which when completed returns an <see cref="ODataProperty"/> representing the read property.</returns>
        public override Task <ODataProperty> ReadPropertyAsync(IEdmStructuralProperty property, IEdmTypeReference expectedPropertyTypeReference)
        {
            this.AssertAsynchronous();
            this.VerifyCanReadProperty();

            ODataJsonLightPropertyAndValueDeserializer jsonLightPropertyAndValueDeserializer = new ODataJsonLightPropertyAndValueDeserializer(this);

            return(jsonLightPropertyAndValueDeserializer.ReadTopLevelPropertyAsync(expectedPropertyTypeReference));
        }
示例#6
0
        /// <summary>
        /// This method creates an reads the property from the input and
        /// returns an <see cref="ODataProperty"/> representing the read property.
        /// </summary>
        /// <param name="property">The <see cref="IEdmProperty"/> producing the property to be read.</param>
        /// <param name="expectedPropertyTypeReference">The expected type reference of the property to read.</param>
        /// <returns>An <see cref="ODataProperty"/> representing the read property.</returns>
        internal override ODataProperty ReadProperty(IEdmStructuralProperty property, IEdmTypeReference expectedPropertyTypeReference)
        {
            DebugUtils.CheckNoExternalCallers();
            this.AssertSynchronous();
            this.VerifyCanReadProperty();

            ODataJsonLightPropertyAndValueDeserializer jsonLightPropertyAndValueDeserializer = new ODataJsonLightPropertyAndValueDeserializer(this);

            return(jsonLightPropertyAndValueDeserializer.ReadTopLevelProperty(expectedPropertyTypeReference));
        }
示例#7
0
        private static object ConvertFromResourceOrCollectionValue(string value, IEdmModel model, IEdmTypeReference typeReference)
        {
            ODataMessageReaderSettings settings = new ODataMessageReaderSettings();

            settings.Validations        &= ~ValidationKinds.ThrowOnUndeclaredPropertyForNonOpenType;
            settings.ReadUntypedAsString = false;

            using (StringReader reader = new StringReader(value))
            {
                ODataMessageInfo messageInfo = new ODataMessageInfo
                {
                    MediaType     = new ODataMediaType(MimeConstants.MimeApplicationType, MimeConstants.MimeJsonSubType),
                    Model         = model,
                    IsResponse    = false,
                    IsAsync       = false,
                    MessageStream = null,
                };

                using (ODataJsonLightInputContext context = new ODataJsonLightInputContext(reader, messageInfo, settings))
                {
                    ODataJsonLightPropertyAndValueDeserializer deserializer = new ODataJsonLightPropertyAndValueDeserializer(context);

                    // TODO: The way JSON array literals look in the URI is different that response payload with an array in it.
                    // The fact that we have to manually setup the underlying reader shows this different in the protocol.
                    // There is a discussion on if we should change this or not.
                    deserializer.JsonReader.Read(); // Move to first thing
                    object rawResult = deserializer.ReadNonEntityValue(
                        null /*payloadTypeName*/,
                        typeReference,
                        null /*DuplicatePropertyNameChecker*/,
                        null /*CollectionWithoutExpectedTypeValidator*/,
                        true /*validateNullValue*/,
                        false /*isTopLevelPropertyValue*/,
                        false /*insideResourceValue*/,
                        null /*propertyName*/);
                    deserializer.ReadPayloadEnd(false);

                    return(rawResult);
                }
            }
        }
示例#8
0
        /// <summary>
        /// Converts the given string <paramref name="value"/> to an ODataComplexValue or ODataCollectionValue and returns it.
        /// Tries in both JSON light and Verbose JSON.
        /// </summary>
        /// <remarks>Does not handle primitive values.</remarks>
        /// <param name="value">Value to be deserialized.</param>
        /// <param name="version">ODataVersion to be compliant with.</param>
        /// <param name="model">Model to use for verification.</param>
        /// <param name="typeReference">Expected type reference from deserialization. If null, verification will be skipped.</param>
        /// <returns>An ODataComplexValue or ODataCollectionValue that results from the deserialization of <paramref name="value"/>.</returns>
        internal static object ConvertFromComplexOrCollectionValue(string value, ODataVersion version, IEdmModel model, IEdmTypeReference typeReference)
        {
            ODataMessageReaderSettings settings = new ODataMessageReaderSettings();

            using (StringReader reader = new StringReader(value))
            {
                using (ODataJsonLightInputContext context = new ODataJsonLightInputContext(
                           ODataFormat.Json,
                           reader,
                           new MediaType(MimeConstants.MimeApplicationType, MimeConstants.MimeJsonSubType),
                           settings,
                           version,
                           false /*readingResponse*/,
                           true /*synchronous*/,
                           model,
                           null /*urlResolver*/,
                           null /*payloadKindDetectionState*/))
                {
                    ODataJsonLightPropertyAndValueDeserializer deserializer = new ODataJsonLightPropertyAndValueDeserializer(context);

                    // TODO: The way JSON array literals look in the URI is different that response payload with an array in it.
                    // The fact that we have to manually setup the underlying reader shows this different in the protocol.
                    // There is a discussion on if we should change this or not.
                    deserializer.JsonReader.Read(); // Move to first thing
                    object rawResult = deserializer.ReadNonEntityValue(
                        null /*payloadTypeName*/,
                        typeReference,
                        null /*DuplicatePropertyNameChecker*/,
                        null /*CollectionWithoutExpectedTypeValidator*/,
                        true /*validateNullValue*/,
                        false /*isTopLevelPropertyValue*/,
                        false /*insideComplexValue*/,
                        null /*propertyName*/);
                    deserializer.ReadPayloadEnd(false);

                    Debug.Assert(rawResult is ODataComplexValue || rawResult is ODataCollectionValue, "rawResult is ODataComplexValue || rawResult is ODataCollectionValue");
                    return(rawResult);
                }
            }
        }
示例#9
0
        private object WriteThenReadValue(object clrValue, IEdmTypeReference typeReference, ODataVersion version, bool isIeee754Compatible)
        {
            var stream = new MemoryStream();

            var settings = new ODataMessageWriterSettings {
                Version = version
            };

            settings.SetServiceDocumentUri(new Uri("http://odata.org/test/"));

            var mediaType = isIeee754Compatible
                ? new ODataMediaType("application", "json", new KeyValuePair <string, string>("IEEE754Compatible", "true"))
                : new ODataMediaType("application", "json");

            var messageInfoForWriter = new ODataMessageInfo
            {
                MessageStream = new NonDisposingStream(stream),
                MediaType     = mediaType,
                Encoding      = Encoding.UTF8,
                IsResponse    = true,
                IsAsync       = false,
                Model         = this.model,
                Container     = this.container
            };

            using (var outputContext = new ODataJsonLightOutputContext(messageInfoForWriter, settings))
            {
                var serializer = new ODataJsonLightValueSerializer(outputContext);
                serializer.WritePrimitiveValue(clrValue, typeReference);
            }

            stream.Position = 0;

            var messageInfoForReader = new ODataMessageInfo
            {
                Encoding      = Encoding.UTF8,
                IsResponse    = true,
                MediaType     = mediaType,
                IsAsync       = false,
                Model         = this.model,
                MessageStream = stream,
                Container     = this.container
            };

            object actualValue;

            using (var inputContext = new ODataJsonLightInputContext(
                       messageInfoForReader, new ODataMessageReaderSettings()))
            {
                var deserializer = new ODataJsonLightPropertyAndValueDeserializer(inputContext);
                deserializer.JsonReader.Read();
                actualValue = deserializer.ReadNonEntityValue(
                    /*payloadTypeName*/ null,
                    typeReference,
                    /*propertyAndAnnotationCollector*/ null,
                    /*collectionValidator*/ null,
                    /*validateNullValue*/ true,
                    /*isTopLevel*/ true,
                    /*insideResourceValue*/ false,
                    /*propertyName*/ null);
            }

            return(actualValue);
        }
示例#10
0
        private object WriteAsUntypedThenReadValue(string value, IEdmTypeReference typeReference, ODataVersion version)
        {
            var stream = new MemoryStream();

            var settings = new ODataMessageWriterSettings {
                Version = version
            };

            settings.SetServiceDocumentUri(new Uri("http://tempuri.org/"));

            var mediaType = new ODataMediaType("application", "json");

            var messageInfoForWriter = new ODataMessageInfo
            {
                MessageStream = new NonDisposingStream(stream),
                MediaType     = mediaType,
                Encoding      = Encoding.UTF8,
                IsResponse    = true,
                IsAsync       = false,
                Model         = this.model,
                Container     = this.container
            };

            using (var outputContext = new ODataJsonLightOutputContext(messageInfoForWriter, settings))
            {
                var serializer = new ODataJsonLightValueSerializer(outputContext);
                // Writing the value as untyped it remains in its original form
                serializer.WriteUntypedValue(new ODataUntypedValue {
                    RawValue = value
                });
            }

            stream.Position = 0;

            var messageInfoForReader = new ODataMessageInfo
            {
                Encoding      = Encoding.UTF8,
                IsResponse    = true,
                MediaType     = mediaType,
                IsAsync       = false,
                Model         = this.model,
                MessageStream = stream,
                Container     = this.container
            };

            object actualValue;

            using (var inputContext = new ODataJsonLightInputContext(
                       messageInfoForReader, new ODataMessageReaderSettings()))
            {
                var deserializer = new ODataJsonLightPropertyAndValueDeserializer(inputContext);
                deserializer.JsonReader.Read();
                actualValue = deserializer.ReadNonEntityValue(
                    /*payloadTypeName*/ null,
                    typeReference,
                    /*propertyAndAnnotationCollector*/ null,
                    /*collectionValidator*/ null,
                    /*validateNullValue*/ true,
                    /*isTopLevel*/ true,
                    /*insideResourceValue*/ false,
                    /*propertyName*/ null);
            }

            return(actualValue);
        }
示例#11
0
        /// <summary>
        /// Converts the given string <paramref name="value"/> to an ODataComplexValue or ODataCollectionValue and returns it.
        /// Tries in both JSON light and Verbose JSON.
        /// </summary>
        /// <remarks>Does not handle primitive values.</remarks>
        /// <param name="value">Value to be deserialized.</param>
        /// <param name="version">ODataVersion to be compliant with.</param>
        /// <param name="model">Model to use for verification.</param>
        /// <param name="typeReference">Expected type reference from deserialization. If null, verification will be skipped.</param>
        /// <returns>An ODataComplexValue or ODataCollectionValue that results from the deserialization of <paramref name="value"/>.</returns>
        internal static object ConvertFromComplexOrCollectionValue(string value, ODataVersion version, IEdmModel model, IEdmTypeReference typeReference)
        {
            DebugUtils.CheckNoExternalCallers();

            ODataMessageReaderSettings settings = new ODataMessageReaderSettings();

            // Try read as JSON (light) so long as a custom model was provided
            if (model.IsUserModel())
            {
                try
                {
                    using (StringReader reader = new StringReader(value))
                    {
                        using (ODataJsonLightInputContext context = new ODataJsonLightInputContext(
                                   ODataFormat.Json,
                                   reader,
                                   new MediaType(MimeConstants.MimeApplicationType, MimeConstants.MimeJsonSubType),
                                   settings,
                                   version,
                                   false /*readingResponse*/,
                                   true /*synchronous*/,
                                   model,
                                   null /*urlResolver*/,
                                   null /*payloadKindDetectionState*/))
                        {
                            ODataJsonLightPropertyAndValueDeserializer deserializer = new ODataJsonLightPropertyAndValueDeserializer(context);

                            // TODO: The way JSON array literals look in the URI is different that response payload with an array in it.
                            // The fact that we have to manually setup the underlying reader shows this different in the protocol.
                            // There is a discussion on if we should change this or not.
                            deserializer.JsonReader.Read(); // Move to first thing
                            object rawResult = deserializer.ReadNonEntityValue(
                                null /*payloadTypeName*/,
                                typeReference,
                                null /*DuplicatePropertyNameChecker*/,
                                null /*CollectionWithoutExpectedTypeValidator*/,
                                true /*validateNullValue*/,
                                false /*isTopLevelPropertyValue*/,
                                false /*insideComplexValue*/,
                                null /*propertyName*/);
                            deserializer.ReadPayloadEnd(false);

                            Debug.Assert(rawResult is ODataComplexValue || rawResult is ODataCollectionValue, "rawResult is ODataComplexValue || rawResult is ODataCollectionValue");
                            return(rawResult);
                        }
                    }
                }
                catch (ODataException)
                {
                    // Swallow. We'll try reading it as Verbose JSON instead.
                    // If an error occurs then, we'll surface that error message.
                    // Since we shipped Verbose JSON only support in 5.0, it's nice to preserve the Verbose JSON error messages.
                }
            }

            // Read as Verbose JSON
            using (StringReader reader = new StringReader(value))
            {
                using (ODataVerboseJsonInputContext context = new ODataVerboseJsonInputContext(
                           ODataFormat.VerboseJson,
                           reader,
                           settings,
                           version,
                           false /*readingResponse*/,
                           true /*synchronous*/,
                           model,
                           null /*urlResolver*/))
                {
                    ODataVerboseJsonPropertyAndValueDeserializer deserializer = new ODataVerboseJsonPropertyAndValueDeserializer(context);

                    deserializer.ReadPayloadStart(false);
                    object rawResult = deserializer.ReadNonEntityValue(
                        typeReference,
                        null /*DuplicatePropertyNameChecker*/,
                        null /*CollectionWithoutExpectedTypeValidator*/,
                        true /*validateNullValue*/,
                        null /*propertyName*/);
                    deserializer.ReadPayloadEnd(false);

                    Debug.Assert(rawResult is ODataComplexValue || rawResult is ODataCollectionValue, "rawResult is ODataComplexValue || rawResult is ODataCollectionValue");
                    return(rawResult);
                }
            }
        }
        /// <summary>
        /// Asynchronously reads a property value which occurs in the "error" object scope.
        /// </summary>
        /// <param name="error">The <see cref="ODataError"/> object to update with the data from this property value.</param>
        /// <param name="propertyName">The name of the property whose value is to be read.</param>
        /// <param name="duplicationPropertyNameChecker"><see cref="PropertyAndAnnotationCollector"/> to use for extracting property annotations
        /// targeting any custom instance annotations on the error.</param>
        /// <returns>A task that represents the asynchronous read operation.</returns>
        /// <remarks>
        /// Pre-Condition:  any                         - The value of the property being read.
        /// Post-Condition: JsonNodeType.Property       - The property after the one being read.
        ///                 JsonNodeType.EndObject      - The end of the "error" object.
        ///                 any                         - Anything else after the property value is an invalid payload (but won't fail in this method).
        /// </remarks>
        private async Task ReadPropertyValueInODataErrorObjectAsync(ODataError error, string propertyName, PropertyAndAnnotationCollector duplicationPropertyNameChecker)
        {
            switch (propertyName)
            {
            case JsonConstants.ODataErrorCodeName:
                error.ErrorCode = await this.JsonReader.ReadStringValueAsync(JsonConstants.ODataErrorCodeName)
                                  .ConfigureAwait(false);

                break;

            case JsonConstants.ODataErrorMessageName:
                error.Message = await this.JsonReader.ReadStringValueAsync(JsonConstants.ODataErrorMessageName)
                                .ConfigureAwait(false);

                break;

            case JsonConstants.ODataErrorTargetName:
                error.Target = await this.JsonReader.ReadStringValueAsync(JsonConstants.ODataErrorTargetName)
                               .ConfigureAwait(false);

                break;

            case JsonConstants.ODataErrorDetailsName:
                error.Details = await this.ReadErrorDetailsAsync()
                                .ConfigureAwait(false);

                break;

            case JsonConstants.ODataErrorInnerErrorName:
                error.InnerError = await this.ReadInnerErrorAsync(recursionDepth : 0)
                                   .ConfigureAwait(false);

                break;

            default:
                // See if it's an instance annotation
                if (ODataJsonLightReaderUtils.IsAnnotationProperty(propertyName))
                {
                    ODataJsonLightPropertyAndValueDeserializer propertyAndValueDeserializer = new ODataJsonLightPropertyAndValueDeserializer(this.JsonLightInputContext);
                    object typeName;

                    duplicationPropertyNameChecker.GetODataPropertyAnnotations(propertyName).TryGetValue(ODataAnnotationNames.ODataType, out typeName);

                    var value = await propertyAndValueDeserializer.ReadNonEntityValueAsync(
                        payloadTypeName : typeName as string,
                        expectedValueTypeReference : null,
                        propertyAndAnnotationCollector : null,
                        collectionValidator : null,
                        validateNullValue : false,
                        isTopLevelPropertyValue : false,
                        insideResourceValue : false,
                        propertyName : propertyName).ConfigureAwait(false);

                    error.GetInstanceAnnotations().Add(new ODataInstanceAnnotation(propertyName, value.ToODataValue()));
                }
                else
                {
                    // We only allow a 'code', 'message', 'target', 'details, and 'innererror' properties
                    // in the value of the 'error' property or custom instance annotations
                    throw new ODataException(Strings.ODataJsonLightErrorDeserializer_TopLevelErrorValueWithInvalidProperty(propertyName));
                }

                break;
            }
        }