/// <summary> /// Read a service document. /// This method reads the service document from the input and returns /// an <see cref="ODataServiceDocument"/> that represents the read service document. /// </summary> /// <returns>A task which returns an <see cref="ODataServiceDocument"/> representing the read service document.</returns> /// <remarks> /// Pre-Condition: JsonNodeType.None: assumes that the JSON reader has not been used yet. /// Post-Condition: JsonNodeType.EndOfInput /// </remarks> internal Task <ODataServiceDocument> ReadServiceDocumentAsync() { Debug.Assert(this.JsonReader.NodeType == JsonNodeType.None, "Pre-Condition: expected JsonNodeType.None, the reader must not have been used yet."); this.JsonReader.AssertNotBuffering(); // We use this to store annotations and check for duplicate annotation names, but we don't really store properties in it. PropertyAndAnnotationCollector propertyAndAnnotationCollector = this.CreatePropertyAndAnnotationCollector(); // Position the reader on the first node return(this.ReadPayloadStartAsync( ODataPayloadKind.ServiceDocument, propertyAndAnnotationCollector, /*isReadingNestedPayload*/ false, /*allowEmptyPayload*/ false) .FollowOnSuccessWith(t => { ODataServiceDocument serviceDocument = this.ReadServiceDocumentImplementation(propertyAndAnnotationCollector); // Read the end of the response. this.ReadPayloadEnd(/*isReadingNestedPayload*/ false); Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndOfInput, "Post-Condition: expected JsonNodeType.EndOfInput"); this.JsonReader.AssertNotBuffering(); return serviceDocument; })); }
public async Task ReadCollectionStartAsync_ThrowsExceptionForTopLevelPropertyAnnotationWithoutProperty() { var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); var expectedItemTypeReference = EdmCoreModel.Instance.GetString(false); var payload = "{\"@odata.context\":\"http://tempuri.org/$metadata#Collection(Edm.String)\"," + "\"[email protected]\":\"foobar\"}"; var exception = await Assert.ThrowsAsync <ODataException>( () => SetupJsonLightCollectionDeserializerAndRunTestAsync( payload, async(jsonLightCollectionDeserializer) => { await jsonLightCollectionDeserializer.ReadPayloadStartAsync( ODataPayloadKind.Collection, propertyAndAnnotationCollector, isReadingNestedPayload: false, allowEmptyPayload: false); var collectionStart = await jsonLightCollectionDeserializer.ReadCollectionStartAsync( propertyAndAnnotationCollector, isReadingNestedPayload: false, expectedItemTypeReference: expectedItemTypeReference); })); Assert.Equal( ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_TopLevelPropertyAnnotationWithoutProperty("value"), exception.Message); }
public async Task ReadCollectionStartAsync_ThrowsExceptionForMetadataReferenceProperty() { var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); var expectedItemTypeReference = EdmCoreModel.Instance.GetString(false); var payload = "{\"@odata.context\":\"http://tempuri.org/$metadata#Collection(Edm.String)\"," + "\"#NS.Func\":{\"title\":\"Func\",\"target\":\"http://tempuri.org/Func\"}," + "\"value\":[\"Tea\",\"Coffee\"]}"; var exception = await Assert.ThrowsAsync <ODataException>( () => SetupJsonLightCollectionDeserializerAndRunTestAsync( payload, async(jsonLightCollectionDeserializer) => { await jsonLightCollectionDeserializer.ReadPayloadStartAsync( ODataPayloadKind.Collection, propertyAndAnnotationCollector, isReadingNestedPayload: false, allowEmptyPayload: false); var collectionStart = await jsonLightCollectionDeserializer.ReadCollectionStartAsync( propertyAndAnnotationCollector, isReadingNestedPayload: false, expectedItemTypeReference: expectedItemTypeReference); })); Assert.Equal( ODataErrorStrings.ODataJsonLightPropertyAndValueDeserializer_UnexpectedMetadataReferenceProperty("#NS.Func"), exception.Message); }
/// <summary> /// Read a set of top-level entity reference links. /// </summary> /// <param name="propertyAndAnnotationCollector">The duplicate property names checker to use for the top-level scope.</param> /// <returns>An <see cref="ODataEntityReferenceLinks"/> representing the read links.</returns> private ODataEntityReferenceLinks ReadEntityReferenceLinksImplementation(PropertyAndAnnotationCollector propertyAndAnnotationCollector) { Debug.Assert(propertyAndAnnotationCollector != null, "propertyAndAnnotationCollector != null"); ODataEntityReferenceLinks entityReferenceLinks = new ODataEntityReferenceLinks(); this.ReadEntityReferenceLinksAnnotations(entityReferenceLinks, propertyAndAnnotationCollector, /*forLinksStart*/ true); // Read the start of the content array of the links this.JsonReader.ReadStartArray(); List <ODataEntityReferenceLink> links = new List <ODataEntityReferenceLink>(); PropertyAndAnnotationCollector linkPropertyAndAnnotationCollector = this.JsonLightInputContext.CreatePropertyAndAnnotationCollector(); while (this.JsonReader.NodeType != JsonNodeType.EndArray) { // read another link ODataEntityReferenceLink entityReferenceLink = this.ReadSingleEntityReferenceLink(linkPropertyAndAnnotationCollector, /*topLevel*/ false); links.Add(entityReferenceLink); linkPropertyAndAnnotationCollector.Reset(); } this.JsonReader.ReadEndArray(); this.ReadEntityReferenceLinksAnnotations(entityReferenceLinks, propertyAndAnnotationCollector, /*forLinksStart*/ false); this.JsonReader.ReadEndObject(); entityReferenceLinks.Links = new ReadOnlyEnumerable <ODataEntityReferenceLink>(links); return(entityReferenceLinks); }
/// <summary> /// Parses JSON object property starting with the current position of the JSON reader. /// </summary> /// <param name="propertyAndAnnotationCollector">The duplicate property names checker to use, it will also store the property annotations found.</param> /// <param name="readPropertyAnnotationValue">Function called to read property annotation value.</param> /// <param name="handleProperty">Function callback to handle the result of parsing property.</param> internal void ProcessProperty( PropertyAndAnnotationCollector propertyAndAnnotationCollector, Func <string, object> readPropertyAnnotationValue, Action <PropertyParsingResult, string> handleProperty) { Debug.Assert(propertyAndAnnotationCollector != null, "propertyAndAnnotationCollector != null"); Debug.Assert(readPropertyAnnotationValue != null, "readPropertyAnnotationValue != null"); Debug.Assert(handleProperty != null, "handleProperty != null"); this.AssertJsonCondition(JsonNodeType.Property); string propertyName; PropertyParsingResult propertyParsingResult = this.ParseProperty( propertyAndAnnotationCollector, readPropertyAnnotationValue, out propertyName); while (propertyParsingResult == PropertyParsingResult.CustomInstanceAnnotation && this.ShouldSkipCustomInstanceAnnotation(propertyName)) { // Read over the property name this.JsonReader.Read(); // Skip over the instance annotation value and don't report it to the OM. this.JsonReader.SkipValue(); propertyParsingResult = this.ParseProperty( propertyAndAnnotationCollector, readPropertyAnnotationValue, out propertyName); } handleProperty(propertyParsingResult, propertyName); if (propertyParsingResult != PropertyParsingResult.EndOfObject && propertyParsingResult != PropertyParsingResult.CustomInstanceAnnotation) { propertyAndAnnotationCollector.MarkPropertyAsProcessed(propertyName); } }
/// <summary> /// Read a top-level error. /// </summary> /// <returns>A task which returns an <see cref="ODataError"/> representing the read error.</returns> /// <remarks> /// Pre-Condition: JsonNodeType.None - The reader must not have been used yet. /// Post-Condition: JsonNodeType.EndOfInput /// </remarks> internal Task <ODataError> ReadTopLevelErrorAsync() { Debug.Assert(this.JsonReader.NodeType == JsonNodeType.None, "Pre-Condition: expected JsonNodeType.None, the reader must not have been used yet."); Debug.Assert(!this.JsonReader.DisableInStreamErrorDetection, "!JsonReader.DisableInStreamErrorDetection"); this.JsonReader.AssertNotBuffering(); // prevent the buffering JSON reader from detecting in-stream errors - we read the error ourselves // to throw proper exceptions this.JsonReader.DisableInStreamErrorDetection = true; // We use this to store annotations and check for duplicate annotation names, but we don't really store properties in it. PropertyAndAnnotationCollector propertyAndAnnotationCollector = this.CreatePropertyAndAnnotationCollector(); // Position the reader on the first node return(this.ReadPayloadStartAsync( ODataPayloadKind.Error, propertyAndAnnotationCollector, /*isReadingNestedPayload*/ false, /*allowEmptyPayload*/ false) .FollowOnSuccessWith(t => { ODataError result = this.ReadTopLevelErrorImplementation(); Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndOfInput, "Post-Condition: JsonNodeType.EndOfInput"); this.JsonReader.AssertNotBuffering(); return result; }) .FollowAlwaysWith(t => { this.JsonReader.DisableInStreamErrorDetection = false; })); }
/// <summary> /// Read a set of top-level entity reference links. /// </summary> /// <returns>A task which returns an <see cref="ODataEntityReferenceLinks"/> representing the read links.</returns> internal async Task <ODataEntityReferenceLinks> ReadEntityReferenceLinksAsync() { Debug.Assert(this.JsonReader.NodeType == JsonNodeType.None, "Pre-Condition: expected JsonNodeType.None, the reader must not have been used yet."); this.JsonReader.AssertNotBuffering(); // We use this to store annotations and check for duplicate annotation names, but we don't really store properties in it. PropertyAndAnnotationCollector propertyAndAnnotationCollector = this.CreatePropertyAndAnnotationCollector(); await this.ReadPayloadStartAsync( ODataPayloadKind.EntityReferenceLinks, propertyAndAnnotationCollector, isReadingNestedPayload : false, allowEmptyPayload : false).ConfigureAwait(false); ODataEntityReferenceLinks entityReferenceLinks = await this.ReadEntityReferenceLinksImplementationAsync( propertyAndAnnotationCollector).ConfigureAwait(false); await this.ReadPayloadEndAsync(isReadingNestedPayload : false) .ConfigureAwait(false); Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndOfInput, "Post-Condition: expected JsonNodeType.EndOfInput"); this.JsonReader.AssertNotBuffering(); return(entityReferenceLinks); }
public ODataJsonLightParameterDeserializerTests() { this.messageReaderSettings = new ODataMessageReaderSettings(); this.InitializeModel(); this.propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); }
/// <summary> /// Implementation of the collection reader logic when in state 'Start'. /// </summary> /// <param name="propertyAndAnnotationCollector">The duplicate property names checker for the top-level scope.</param> /// <returns>true if more items can be read from the reader; otherwise false.</returns> /// <remarks> /// Pre-Condition: JsonNodeType.None: assumes that the JSON reader has not been used yet when not reading a nested payload. /// Post-Condition: The reader is positioned on the first node of the first item or the EndArray node of an empty item array /// </remarks> private bool ReadAtStartImplementationSynchronously(PropertyAndAnnotationCollector propertyAndAnnotationCollector) { Debug.Assert(propertyAndAnnotationCollector != null, "propertyAndAnnotationCollector != null"); IEdmTypeReference actualItemTypeReference; this.ExpectedItemTypeReference = ReaderValidationUtils.ValidateCollectionContextUriAndGetPayloadItemTypeReference( this.jsonLightCollectionDeserializer.ContextUriParseResult, this.ExpectedItemTypeReference); // read the start of the collection until we find the content array for top-level collections ODataCollectionStart collectionStart = this.jsonLightCollectionDeserializer.ReadCollectionStart( propertyAndAnnotationCollector, this.IsReadingNestedPayload, this.ExpectedItemTypeReference, out actualItemTypeReference); if (actualItemTypeReference != null) { this.ExpectedItemTypeReference = actualItemTypeReference; } this.jsonLightCollectionDeserializer.JsonReader.ReadStartArray(); this.EnterScope(ODataCollectionReaderState.CollectionStart, collectionStart); return(true); }
/// <summary> /// Asynchronous implementation of the collection reader logic when in state 'Start'. /// </summary> /// <param name="propertyAndAnnotationCollector">The duplicate property names checker for the top-level scope.</param> /// <returns> /// A task that represents the asynchronous read operation. /// The value of the TResult parameter contains true if more items can be read from the reader; otherwise false. /// </returns> /// <remarks> /// Pre-Condition: JsonNodeType.None: assumes that the JSON reader has not been used yet when not reading a nested payload. /// Post-Condition: The reader is positioned on the first node of the first item or the EndArray node of an empty item array /// </remarks> private async Task <bool> ReadAtStartImplementationAsynchronously(PropertyAndAnnotationCollector propertyAndAnnotationCollector) { Debug.Assert(propertyAndAnnotationCollector != null, "propertyAndAnnotationCollector != null"); IEdmTypeReference actualItemTypeReference; this.ExpectedItemTypeReference = ReaderValidationUtils.ValidateCollectionContextUriAndGetPayloadItemTypeReference( this.jsonLightCollectionDeserializer.ContextUriParseResult, this.ExpectedItemTypeReference); // Read the start of the collection until we find the content array for top-level collections Tuple <ODataCollectionStart, IEdmTypeReference> readCollectionStartResult = await this.jsonLightCollectionDeserializer.ReadCollectionStartAsync( propertyAndAnnotationCollector, this.IsReadingNestedPayload, this.ExpectedItemTypeReference).ConfigureAwait(false); ODataCollectionStart collectionStart = readCollectionStartResult.Item1; actualItemTypeReference = readCollectionStartResult.Item2; if (actualItemTypeReference != null) { this.ExpectedItemTypeReference = actualItemTypeReference; } await this.jsonLightCollectionDeserializer.JsonReader.ReadStartArrayAsync() .ConfigureAwait(false); this.EnterScope(ODataCollectionReaderState.CollectionStart, collectionStart); return(true); }
/// <summary> /// Read the start of the top-level data wrapper in JSON responses. /// </summary> /// <param name="payloadKind">The kind of payload we are reading; this guides the parsing of the context URI.</param> /// <param name="propertyAndAnnotationCollector">The duplicate property names checker.</param> /// <param name="isReadingNestedPayload">true if we are deserializing a nested payload, e.g. a resource, a resource set or a collection within a parameters payload.</param> /// <param name="allowEmptyPayload">true if we allow a completely empty payload; otherwise false.</param> /// <returns>The parsed context URI.</returns> /// <remarks> /// Pre-Condition: JsonNodeType.None: assumes that the JSON reader has not been used yet when not reading a nested payload. /// Post-Condition: The reader is positioned on the first property of the payload after having read (or skipped) the context URI property. /// Or the reader is positioned on an end-object node if there are no properties (other than the context URI which is required in responses and optional in requests). /// </remarks> internal Task ReadPayloadStartAsync( ODataPayloadKind payloadKind, PropertyAndAnnotationCollector propertyAndAnnotationCollector, bool isReadingNestedPayload, bool allowEmptyPayload) { this.JsonReader.AssertNotBuffering(); Debug.Assert(isReadingNestedPayload || this.JsonReader.NodeType == JsonNodeType.None, "Pre-Condition: JSON reader must not have been used yet when not reading a nested payload."); return(TaskUtils.GetTaskForSynchronousOperation(() => { string contextUriAnnotationValue = this.ReadPayloadStartImplementation( payloadKind, propertyAndAnnotationCollector, isReadingNestedPayload, allowEmptyPayload); // The context URI is only recognized in non-error response top-level payloads. // If the payload is nested (for example when we read URL literals) we don't recognize the context URI. // Top-level error payloads don't need and use the context URI. if (!isReadingNestedPayload && payloadKind != ODataPayloadKind.Error && contextUriAnnotationValue != null) { this.contextUriParseResult = ODataJsonLightContextUriParser.Parse( this.Model, contextUriAnnotationValue, payloadKind, this.MessageReaderSettings.ClientCustomTypeResolver, this.JsonLightInputContext.ReadingResponse); } #if DEBUG this.contextUriParseResultReady = true; #endif })); }
/// <summary> /// Reads the odata.context annotation. /// </summary> /// <param name="payloadKind">The payload kind for which to read the context URI.</param> /// <param name="propertyAndAnnotationCollector">The duplicate property names checker.</param> /// <param name="failOnMissingContextUriAnnotation">true if the method should fail if the context URI annotation is missing, false if that can be ignored.</param> /// <returns>The value of the context URI annotation.</returns> internal string ReadContextUriAnnotation( ODataPayloadKind payloadKind, PropertyAndAnnotationCollector propertyAndAnnotationCollector, bool failOnMissingContextUriAnnotation) { if (this.JsonReader.NodeType != JsonNodeType.Property) { if (!failOnMissingContextUriAnnotation || payloadKind == ODataPayloadKind.Unsupported) { // Do not fail during payload kind detection return(null); } throw new ODataException(Strings.ODataJsonLightDeserializer_ContextLinkNotFoundAsFirstProperty); } // Must make sure the input odata.context has a '@' prefix string propertyName = this.JsonReader.GetPropertyName(); if (string.CompareOrdinal(JsonLightConstants.ODataPropertyAnnotationSeparatorChar + ODataAnnotationNames.ODataContext, propertyName) != 0 && !this.CompareSimplifiedODataAnnotation(JsonLightConstants.SimplifiedODataContextPropertyName, propertyName)) { if (!failOnMissingContextUriAnnotation || payloadKind == ODataPayloadKind.Unsupported) { // Do not fail during payload kind detection return(null); } throw new ODataException(Strings.ODataJsonLightDeserializer_ContextLinkNotFoundAsFirstProperty); } // Read over the property name this.JsonReader.ReadNext(); return(this.JsonReader.ReadStringValue()); }
public void OnlyCustomAnnotationsForPropertyAddedShouldReturnEmpty() { PropertyAndAnnotationCollector duplicateChecker = new PropertyAndAnnotationCollector(true); duplicateChecker.AddCustomPropertyAnnotation("property", "custom.annotation", "value"); duplicateChecker.AddCustomPropertyAnnotation("property", "custom.annotation2", "value"); duplicateChecker.GetODataPropertyAnnotations("property").Should().BeEmpty(); }
public void DuplicatePropertyCustomAnnotationShouldNotFail() { PropertyAndAnnotationCollector duplicateChecker = new PropertyAndAnnotationCollector(true); Action action = () => duplicateChecker.AddCustomPropertyAnnotation("property", "custom.name", "value"); action.ShouldNotThrow(); action.ShouldNotThrow(); }
public void DuplicatePropertyODataAnnotationShouldFail() { PropertyAndAnnotationCollector duplicateChecker = new PropertyAndAnnotationCollector(true); Action action = () => duplicateChecker.AddODataPropertyAnnotation("property", JsonLightConstants.ODataAnnotationNamespacePrefix + "name", "SomeValue"); action.ShouldNotThrow(); action.ShouldThrow <ODataException>().WithMessage(ErrorStrings.DuplicateAnnotationForPropertyNotAllowed(JsonLightConstants.ODataAnnotationNamespacePrefix + "name", "property")); }
public void DuplicateInstanceODataAnnotationShouldFail() { PropertyAndAnnotationCollector duplicateChecker = new PropertyAndAnnotationCollector(true); Action action = () => duplicateChecker.MarkPropertyAsProcessed(JsonLightConstants.ODataAnnotationNamespacePrefix + "name"); action.ShouldNotThrow(); action.ShouldThrow <ODataException>().WithMessage(ErrorStrings.DuplicateAnnotationNotAllowed(JsonLightConstants.ODataAnnotationNamespacePrefix + "name")); }
public void ReadInstanceAnnotationValueWillReadJsonNativeTypesWithoutODataType() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@odata.Int32Annotation\":123}"); AdvanceReaderToFirstPropertyValue(deserializer.JsonReader); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); Assert.Equal(123, deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "odata.Int32Annotation")); }
public void ReadInstanceAnnotationValueWillReadNonJsonNativePrimitiveTypesWithoutODataTypeAsStringValue() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@Custom.GuidAnnotation\":\"00000000-0000-0000-0000-000000000000\"}"); AdvanceReaderToFirstPropertyValue(deserializer.JsonReader); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "Custom.GuidAnnotation").Should().Be("00000000-0000-0000-0000-000000000000"); }
public void ReadInstanceAnnotationValueWillReadNullValueWithoutODataType() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@odata.NullAnnotation\":null}"); AdvanceReaderToFirstPropertyValue(deserializer.JsonReader); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "odata.NullAnnotation").Should().BeNull(); }
public void ReadInstanceAnnotationValueWillReadAsCorrectTypePrimitiveTypesWithODataTypeAnnotation() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@Custom.GuidAnnotation\":\"00000000-0000-0000-0000-000000000000\"}"); AdvanceReaderToFirstPropertyValue(deserializer.JsonReader); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); propertyAndAnnotationCollector.AddODataPropertyAnnotation("Custom.GuidAnnotation", "odata.type", "Edm.Guid"); deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "Custom.GuidAnnotation").Should().Be(Guid.Empty); }
public void ReadEntryInstanceAnnotationShouldReadCustomInstanceAnnotationValue() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.Int32Annotation\":123}"); AdvanceReaderToFirstPropertyValue(deserializer.JsonReader); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); object value = deserializer.ReadEntryInstanceAnnotation("custom.Int32Annotation", false /*anyPropertyFound*/, true /*typeAnnotationFound*/, propertyAndAnnotationCollector); Assert.Equal(123, value); }
public void ReadInstanceAnnotationValueWillReadNullValueWithODataType() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@odata.NullAnnotation\":null}"); AdvanceReaderToFirstPropertyValue(deserializer.JsonReader); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); propertyAndAnnotationCollector.AddODataPropertyAnnotation("odata.NullAnnotation", "odata.type", "Edm.Guid"); Assert.Null(deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "odata.NullAnnotation")); }
/// <summary> /// Reads the end of a collection; this includes collection-level instance annotations. /// </summary> /// <param name="isReadingNestedPayload">true if we are reading a nested collection inside a paramter payload; otherwise false.</param> /// <remarks> /// Pre-Condition: EndArray node: End of the collection content array /// Post-Condition: EndOfInput: All of the collection payload has been consumed. /// </remarks> internal void ReadCollectionEnd(bool isReadingNestedPayload) { Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndArray, "Pre-condition: JsonNodeType.EndArray"); this.JsonReader.AssertNotBuffering(); this.JsonReader.ReadEndArray(); if (!isReadingNestedPayload) { // Create a new duplicate property names checker object here; we don't have to use the one from reading the // collection start since we don't allow any annotations/properties after the collection property. PropertyAndAnnotationCollector collectionEndPropertyAndAnnotationCollector = this.CreatePropertyAndAnnotationCollector(); // Fail on anything after the collection that is not a custom instance annotation while (this.JsonReader.NodeType == JsonNodeType.Property) { this.ProcessProperty( collectionEndPropertyAndAnnotationCollector, this.ReadTypePropertyAnnotationValue, (propertyParsingResult, propertyName) => { // This method will allow and skip over any custom annotations, but will not report them as enum values, so any result we get other than EndOfObject indicates a malformed payload. switch (propertyParsingResult) { case PropertyParsingResult.CustomInstanceAnnotation: this.JsonReader.SkipValue(); break; case PropertyParsingResult.ODataInstanceAnnotation: if (!IsValidODataAnnotationOfCollection(propertyName)) { throw new ODataException(ODataErrorStrings.ODataJsonLightCollectionDeserializer_CannotReadCollectionEnd(propertyName)); } this.JsonReader.SkipValue(); break; case PropertyParsingResult.PropertyWithoutValue: // fall through case PropertyParsingResult.PropertyWithValue: // fall through case PropertyParsingResult.MetadataReferenceProperty: throw new ODataException(ODataErrorStrings.ODataJsonLightCollectionDeserializer_CannotReadCollectionEnd(propertyName)); case PropertyParsingResult.EndOfObject: break; default: throw new ODataException(ODataErrorStrings.General_InternalError(InternalErrorCodes.ODataJsonLightCollectionDeserializer_ReadCollectionEnd)); } }); } // read the end-object node of the value containing the 'value' property this.JsonReader.ReadEndObject(); } }
public void ReadInstanceAnnotationValueWhenODataTypeAnnotationIsMissingForCollectionValue() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@OData.CollectionAnnotation\":[]}"); AdvanceReaderToFirstPropertyValue(deserializer.JsonReader); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); object tmp = deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "OData.CollectionAnnotation"); tmp.As <ODataCollectionValue>().Items.Cast <string>().Count().Should().Be(0); tmp.As <ODataCollectionValue>().TypeName.ShouldBeEquivalentTo(null); }
public void ReadTopLevelResourceSetAnnotationsForFeedEndAndBufferingShouldSkipAllValues() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.before\":123,\"value\":[],\"@custom.after\":456}"); AdvanceReaderToFirstProperty(deserializer.JsonReader); var feed = new ODataResourceSet(); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); deserializer.ReadTopLevelResourceSetAnnotations(feed, propertyAndAnnotationCollector, false /*forResourceSetStart*/, true /*readAllFeedProperties*/); feed.InstanceAnnotations.Should().BeEmpty(); }
public void ReadTopLevelResourceSetAnnotationsForFeedEndAndNonBufferingShouldSkipInstanceAnnotationsBasedOnReaderSettings() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.after\":456}", shouldReadAndValidateCustomInstanceAnnotations: false); AdvanceReaderToFirstProperty(deserializer.JsonReader); var feed = new ODataResourceSet(); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); deserializer.ReadTopLevelResourceSetAnnotations(feed, propertyAndAnnotationCollector, false /*forResourceSetStart*/, false /*readAllFeedProperties*/); Assert.Equal(0, feed.InstanceAnnotations.Count); }
public void ReadAndApplyResourceSetInstanceAnnotationValueShouldSetInstanceAnnotationOnFeed() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.Int32Annotation\":123}"); AdvanceReaderToFirstPropertyValue(deserializer.JsonReader); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); ODataResourceSet feed = new ODataResourceSet(); deserializer.ReadAndApplyResourceSetInstanceAnnotationValue("custom.Int32Annotation", feed, propertyAndAnnotationCollector); Assert.Equal(1, feed.InstanceAnnotations.Count); TestUtils.AssertODataValueAreEqual(new ODataPrimitiveValue(123), feed.InstanceAnnotations.Single(ia => ia.Name == "custom.Int32Annotation").Value); }
public void ReadDateTypeInstanceAnnotationValueWillReadAsCorrectTypeFromModel() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.DateAnnotation\":\"2013-01-25\"}"); AdvanceReaderToFirstPropertyValue(deserializer.JsonReader); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); object value = deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "custom.DateAnnotation"); value.Should().BeOfType <Date>(); value.Should().Be(Date.Parse("2013-01-25")); }
public void ReadTimeOfDayTypeInstanceAnnotationValueWillReadAsCorrectTypeFromModel() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.TimeOfDayAnnotation\":\"12:30:40.900\"}"); AdvanceReaderToFirstPropertyValue(deserializer.JsonReader); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); object value = deserializer.ReadCustomInstanceAnnotationValue(propertyAndAnnotationCollector, "custom.TimeOfDayAnnotation"); value.Should().BeOfType <TimeOfDay>(); value.Should().Be(TimeOfDay.Parse("12:30:40.900")); }
public void ReadTopLevelResourceSetAnnotationsForFeedEndAndNonBufferingShouldReadRemainingInstanceAnnotationsAfterValue() { var deserializer = this.CreateJsonLightEntryAndFeedDeserializer("{\"@custom.after\":456}"); AdvanceReaderToFirstProperty(deserializer.JsonReader); var feed = new ODataResourceSet(); var propertyAndAnnotationCollector = new PropertyAndAnnotationCollector(true); deserializer.ReadTopLevelResourceSetAnnotations(feed, propertyAndAnnotationCollector, false /*forResourceSetStart*/, false /*readAllFeedProperties*/); Assert.Equal(1, feed.InstanceAnnotations.Count); TestUtils.AssertODataValueAreEqual(new ODataPrimitiveValue(456), feed.InstanceAnnotations.Single(ia => ia.Name == "custom.after").Value); }