/// <summary> /// Converts a <see cref="ODataCollectionValue"/> to a string for use in a Url. /// </summary> /// <param name="collectionValue">Instance to convert.</param> /// <param name="model">Model to be used for validation. User model is optional. The EdmLib core model is expected as a minimum.</param> /// <param name="version">Version to be compliant with. Collection requires >= V3.</param> /// <param name="format">ODataFormat to use for the format of the literal.</param> /// <returns>A string representation of <paramref name="collectionValue"/> to be added to a Url.</returns> internal static string ConvertToUriCollectionLiteral(ODataCollectionValue collectionValue, IEdmModel model, ODataVersion version, ODataFormat format) { DebugUtils.CheckNoExternalCallers(); ExceptionUtils.CheckArgumentNotNull(collectionValue, "collectionValue"); ExceptionUtils.CheckArgumentNotNull(model, "model"); ODataVersionChecker.CheckCollectionValue(version); StringBuilder builder = new StringBuilder(); using (TextWriter textWriter = new StringWriter(builder, CultureInfo.InvariantCulture)) { ODataMessageWriterSettings messageWriterSettings = new ODataMessageWriterSettings() { Version = version, Indent = false }; if (format == ODataFormat.VerboseJson) { WriteJsonVerboseLiteral( model, messageWriterSettings, textWriter, (serializer) => serializer.WriteCollectionValue( collectionValue, null /*metadataTypeReference*/, false /*isOpenPropertyType*/)); } else if (format == ODataFormat.Json) { WriteJsonLightLiteral( model, messageWriterSettings, textWriter, (serializer) => serializer.WriteCollectionValue( collectionValue, null /*metadataTypeReference*/, false /*isTopLevelProperty*/, true /*isInUri*/, false /*isOpenPropertyType*/)); } else { throw new ArgumentException(ODataErrorStrings.ODataUriUtils_ConvertToUriLiteralUnsupportedFormat(format.ToString())); } } return(builder.ToString()); }
internal static string ConvertToUriCollectionLiteral(ODataCollectionValue collectionValue, IEdmModel model, ODataVersion version) { ExceptionUtils.CheckArgumentNotNull<ODataCollectionValue>(collectionValue, "collectionValue"); ExceptionUtils.CheckArgumentNotNull<IEdmModel>(model, "model"); ODataVersionChecker.CheckCollectionValue(version); StringBuilder sb = new StringBuilder(); using (TextWriter writer = new StringWriter(sb, CultureInfo.InvariantCulture)) { JsonWriter jsonWriter = new JsonWriter(writer, false); ODataMessageWriterSettings messageWriterSettings = new ODataMessageWriterSettings { Version = new ODataVersion?(version) }; using (ODataJsonOutputContext context = ODataJsonOutputContext.Create(ODataFormat.VerboseJson, jsonWriter, messageWriterSettings, false, model, null)) { new ODataJsonPropertyAndValueSerializer(context).WriteCollectionValue(collectionValue, null, false); } } return sb.ToString(); }
/// <summary> /// Converts a <see cref="ODataCollectionValue"/> to a string for use in a Url. /// </summary> /// <param name="collectionValue">Instance to convert.</param> /// <param name="model">Model to be used for validation. User model is optional. The EdmLib core model is expected as a minimum.</param> /// <param name="version">Version to be compliant with. Collection requires >= V3.</param> /// <returns>A string representation of <paramref name="collectionValue"/> to be added to a Url.</returns> internal static string ConvertToUriCollectionLiteral(ODataCollectionValue collectionValue, IEdmModel model, ODataVersion version) { DebugUtils.CheckNoExternalCallers(); ExceptionUtils.CheckArgumentNotNull(collectionValue, "collectionValue"); ExceptionUtils.CheckArgumentNotNull(model, "model"); ODataVersionChecker.CheckCollectionValue(version); StringBuilder builder = new StringBuilder(); using (TextWriter textWriter = new StringWriter(builder, CultureInfo.InvariantCulture)) { JsonWriter jsonWriter = new JsonWriter(textWriter, false); ODataMessageWriterSettings messageWriterSettings = new ODataMessageWriterSettings() { Version = version }; // Calling dispose since it's the right thing to do, but when created from JsonWriter // the output context Dispose will not actually dispose anything, it will just cleanup itself. using (ODataJsonOutputContext jsonOutputContext = ODataJsonOutputContext.Create( ODataFormat.VerboseJson, jsonWriter, messageWriterSettings, false /*writingResponse*/, model, null /*urlResolver*/)) { ODataJsonPropertyAndValueSerializer jsonPropertyAndValueSerializer = new ODataJsonPropertyAndValueSerializer(jsonOutputContext); jsonPropertyAndValueSerializer.WriteCollectionValue( collectionValue, null, /*propertyTypeRefereence*/ false /*openPropertyType - this determines if the TypeName will be written*/); jsonPropertyAndValueSerializer.AssertRecursionDepthIsZero(); } } return(builder.ToString()); }
/// <summary> /// Reads a collection value. /// </summary> /// <param name="collectionValueTypeReference">The collection type reference of the value.</param> /// <param name="payloadTypeName">The type name read from the payload.</param> /// <param name="serializationTypeNameAnnotation">The serialization type name for the collection value (possibly null).</param> /// <returns>The value of the collection.</returns> /// <remarks> /// Pre-Condition: Fails if the current node is not a JsonNodeType.StartObject /// Post-Condition: almost anything - the node after the collection value (after the EndObject) /// </remarks> private ODataCollectionValue ReadCollectionValueImplementation( IEdmCollectionTypeReference collectionValueTypeReference, string payloadTypeName, SerializationTypeNameAnnotation serializationTypeNameAnnotation) { DebugUtils.CheckNoExternalCallers(); Debug.Assert( collectionValueTypeReference == null || collectionValueTypeReference.IsNonEntityCollectionType(), "If the metadata is specified it must denote a Collection for this method to work."); this.JsonReader.AssertNotBuffering(); ODataVersionChecker.CheckCollectionValue(this.Version); this.IncreaseRecursionDepth(); // Read over the start object this.JsonReader.ReadStartObject(); ODataCollectionValue collectionValue = new ODataCollectionValue(); collectionValue.TypeName = collectionValueTypeReference != null?collectionValueTypeReference.ODataFullName() : payloadTypeName; if (serializationTypeNameAnnotation != null) { collectionValue.SetAnnotation(serializationTypeNameAnnotation); } List <object> items = null; bool metadataPropertyFound = false; while (this.JsonReader.NodeType == JsonNodeType.Property) { string propertyName = this.JsonReader.ReadPropertyName(); if (string.CompareOrdinal(JsonConstants.ODataMetadataName, propertyName) == 0) { // __metadata property if (metadataPropertyFound) { throw new ODataException(ODataErrorStrings.ODataJsonPropertyAndValueDeserializer_MultiplePropertiesInCollectionWrapper(JsonConstants.ODataMetadataName)); } metadataPropertyFound = true; // Note that we don't need to read the type name again, as we've already read it above in FindTypeNameInPayload. // There's nothing else of interest in the __metadata for collections. this.JsonReader.SkipValue(); } else if (string.CompareOrdinal(JsonConstants.ODataResultsName, propertyName) == 0) { // results property if (items != null) { throw new ODataException(ODataErrorStrings.ODataJsonPropertyAndValueDeserializer_MultiplePropertiesInCollectionWrapper(JsonConstants.ODataResultsName)); } items = new List <object>(); this.JsonReader.ReadStartArray(); DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker(); IEdmTypeReference itemType = null; if (collectionValueTypeReference != null) { itemType = collectionValueTypeReference.CollectionDefinition().ElementType; } // NOTE: we do not support reading Verbose JSON without metadata right now so we always have an expected item type; // The collection validator is always null. CollectionWithoutExpectedTypeValidator collectionValidator = null; while (this.JsonReader.NodeType != JsonNodeType.EndArray) { object itemValue = this.ReadNonEntityValueImplementation( itemType, duplicatePropertyNamesChecker, collectionValidator, /*validateNullValue*/ true, /*propertyName*/ null); // Validate the item (for example that it's not null) ValidationUtils.ValidateCollectionItem(itemValue, false /* isStreamable */); // Note that the ReadNonEntityValue already validated that the actual type of the value matches // the expected type (the itemType). items.Add(itemValue); } Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndArray, "The results value must end with an end array."); this.JsonReader.ReadEndArray(); } else { // Skip over any other property in the collection object this.JsonReader.SkipValue(); } } Debug.Assert(this.JsonReader.NodeType == JsonNodeType.EndObject, "After all properties of Collection wrapper are read the EndObject node is expected."); this.JsonReader.ReadEndObject(); if (items == null) { // We didn't find any results property. All collections must have the results property. throw new ODataException(ODataErrorStrings.ODataJsonPropertyAndValueDeserializer_CollectionWithoutResults); } collectionValue.Items = new ReadOnlyEnumerable(items); this.JsonReader.AssertNotBuffering(); this.DecreaseRecursionDepth(); return(collectionValue); }
private ODataCollectionValue ReadCollectionValueImplementation(IEdmCollectionTypeReference collectionValueTypeReference, string payloadTypeName, SerializationTypeNameAnnotation serializationTypeNameAnnotation) { ODataVersionChecker.CheckCollectionValue(base.Version); this.IncreaseRecursionDepth(); base.JsonReader.ReadStartObject(); ODataCollectionValue value2 = new ODataCollectionValue { TypeName = (collectionValueTypeReference != null) ? collectionValueTypeReference.ODataFullName() : payloadTypeName }; if (serializationTypeNameAnnotation != null) { value2.SetAnnotation <SerializationTypeNameAnnotation>(serializationTypeNameAnnotation); } List <object> sourceEnumerable = null; bool flag = false; while (base.JsonReader.NodeType == JsonNodeType.Property) { string strB = base.JsonReader.ReadPropertyName(); if (string.CompareOrdinal("__metadata", strB) == 0) { if (flag) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_MultiplePropertiesInCollectionWrapper("__metadata")); } flag = true; base.JsonReader.SkipValue(); } else { if (string.CompareOrdinal("results", strB) == 0) { if (sourceEnumerable != null) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_MultiplePropertiesInCollectionWrapper("results")); } sourceEnumerable = new List <object>(); base.JsonReader.ReadStartArray(); DuplicatePropertyNamesChecker duplicatePropertyNamesChecker = base.CreateDuplicatePropertyNamesChecker(); IEdmTypeReference expectedTypeReference = null; if (collectionValueTypeReference != null) { expectedTypeReference = collectionValueTypeReference.CollectionDefinition().ElementType; } CollectionWithoutExpectedTypeValidator collectionValidator = null; while (base.JsonReader.NodeType != JsonNodeType.EndArray) { object item = this.ReadNonEntityValueImplementation(expectedTypeReference, duplicatePropertyNamesChecker, collectionValidator, true); ValidationUtils.ValidateCollectionItem(item, false); sourceEnumerable.Add(item); } base.JsonReader.ReadEndArray(); continue; } base.JsonReader.SkipValue(); } } base.JsonReader.ReadEndObject(); if (sourceEnumerable == null) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_CollectionWithoutResults); } value2.Items = new ReadOnlyEnumerable(sourceEnumerable); this.DecreaseRecursionDepth(); return(value2); }