internal void WritePrimitiveValue(object value, CollectionWithoutExpectedTypeValidator collectionValidator, IEdmTypeReference expectedTypeReference) { IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (collectionValidator != null) { if (primitiveTypeReference == null) { throw new ODataException(Microsoft.Data.OData.Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName)); } collectionValidator.ValidateCollectionItem(primitiveTypeReference.FullName(), EdmTypeKind.Primitive); } if (expectedTypeReference != null) { ValidationUtils.ValidateIsExpectedPrimitiveType(value, primitiveTypeReference, expectedTypeReference); } if ((primitiveTypeReference != null) && primitiveTypeReference.IsSpatial()) { string typeName = primitiveTypeReference.FullName(); PrimitiveConverter.Instance.WriteJson(value, base.JsonWriter, typeName, base.Version); } else { base.JsonWriter.WritePrimitiveValue(value, base.Version); } }
/// <summary> /// Writes a primitive value. /// Uses a registered primitive type converter to write the value if one is registered for the type, otherwise directly writes the value. /// </summary> /// <param name="value">The value to write.</param> /// <param name="expectedTypeReference">The expected type reference of the primitive value.</param> public void WritePrimitiveValue( object value, IEdmTypeReference expectedTypeReference) { Debug.Assert(value != null, "value != null"); // Try convert primitive values from their actual CLR types to their underlying CLR types. value = this.Model.ConvertToUnderlyingTypeIfUIntValue(value, expectedTypeReference); IEdmPrimitiveTypeReference actualTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); ODataPayloadValueConverter converter = this.Model.GetPayloadValueConverter(); // Skip validation if user has set custom PayloadValueConverter if (expectedTypeReference != null && converter.GetType() == typeof(ODataPayloadValueConverter)) { ValidationUtils.ValidateIsExpectedPrimitiveType(value, actualTypeReference, expectedTypeReference, !this.JsonLightOutputContext.MessageWriterSettings.EnableFullValidation); } value = converter.ConvertToPayloadValue(value, expectedTypeReference); if (actualTypeReference != null && actualTypeReference.IsSpatial()) { PrimitiveConverter.Instance.WriteJsonLight(value, this.JsonWriter); } else { this.JsonWriter.WritePrimitiveValue(value); } }
private static IEdmPrimitiveTypeReference GetPrimitiveTypeReferenceFromTypeAndFacets(Type clrType, List <KeyValuePair <string, object> > annotations) { IEdmPrimitiveTypeReference primitiveTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(clrType); if (primitiveTypeReference.IsSpatial()) { primitiveTypeReference = new EdmSpatialTypeReference(primitiveTypeReference.PrimitiveDefinition(), primitiveTypeReference.IsNullable, null); } return(primitiveTypeReference.ApplyFacetAnnotations(annotations)); }
private object ReadNonEntityValueImplementation(IEdmTypeReference expectedTypeReference, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, CollectionWithoutExpectedTypeValidator collectionValidator, bool validateNullValue) { object obj2; SerializationTypeNameAnnotation annotation; EdmTypeKind kind; JsonNodeType nodeType = base.JsonReader.NodeType; if (nodeType == JsonNodeType.StartArray) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_CannotReadPropertyValue(nodeType)); } if (this.TryReadNullValue(expectedTypeReference, validateNullValue)) { return(null); } string payloadTypeName = this.FindTypeNameInPayload(); IEdmTypeReference type = ReaderValidationUtils.ResolvePayloadTypeNameAndComputeTargetType(EdmTypeKind.None, null, expectedTypeReference, payloadTypeName, base.Model, base.MessageReaderSettings, base.Version, new Func <EdmTypeKind>(this.GetNonEntityValueKind), out kind, out annotation); switch (kind) { case EdmTypeKind.Primitive: { IEdmPrimitiveTypeReference reference2 = (type == null) ? null : type.AsPrimitive(); if ((payloadTypeName != null) && !reference2.IsSpatial()) { throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_InvalidPrimitiveTypeName(payloadTypeName)); } obj2 = this.ReadPrimitiveValueImplementation(reference2, validateNullValue); break; } case EdmTypeKind.Complex: obj2 = this.ReadComplexValueImplementation((type == null) ? null : type.AsComplex(), payloadTypeName, annotation, duplicatePropertyNamesChecker); break; case EdmTypeKind.Collection: { IEdmCollectionTypeReference collectionValueTypeReference = ValidationUtils.ValidateCollectionType(type); obj2 = this.ReadCollectionValueImplementation(collectionValueTypeReference, payloadTypeName, annotation); break; } default: throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ODataJsonPropertyAndValueDeserializer_ReadPropertyValue)); } if (collectionValidator != null) { string collectionItemTypeName = ODataJsonReaderUtils.GetPayloadTypeName(obj2); collectionValidator.ValidateCollectionItem(collectionItemTypeName, kind); } return(obj2); }
private object ReadPrimitiveValueImplementation(IEdmPrimitiveTypeReference expectedValueTypeReference, bool validateNullValue) { if ((expectedValueTypeReference != null) && expectedValueTypeReference.IsSpatial()) { return(this.ReadSpatialValue(expectedValueTypeReference, validateNullValue)); } object obj2 = base.JsonReader.ReadPrimitiveValue(); if ((expectedValueTypeReference != null) && !base.MessageReaderSettings.DisablePrimitiveTypeConversion) { obj2 = ODataJsonReaderUtils.ConvertValue(obj2, expectedValueTypeReference, base.MessageReaderSettings, base.Version, validateNullValue); } return(obj2); }
/// <summary> /// Try and parse spatial type from the json payload. /// </summary> /// <param name="jsonReader">The JSON reader to read from.</param> /// <param name="insideJsonObjectValue">true if the reader is positioned on the first property of the value which is a JSON Object /// (or the second property if the first one was odata.type).</param> /// <param name="inputContext">The input context with all the settings.</param> /// <param name="expectedValueTypeReference">Expected edm property type.</param> /// <param name="validateNullValue">true to validate null values; otherwise false.</param> /// <param name="recursionDepth">The recursion depth to start with.</param> /// <param name="propertyName">The name of the property whose value is being read, if applicable (used for error reporting).</param> /// <returns>An instance of the spatial type.</returns> internal static ISpatial ReadSpatialValue( BufferingJsonReader jsonReader, bool insideJsonObjectValue, ODataInputContext inputContext, IEdmPrimitiveTypeReference expectedValueTypeReference, bool validateNullValue, int recursionDepth, string propertyName) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(jsonReader != null, "jsonReader != null"); Debug.Assert(inputContext != null, "inputContext != null"); Debug.Assert(expectedValueTypeReference != null, "expectedValueTypeReference != null"); Debug.Assert(expectedValueTypeReference.IsSpatial(), "TryParseSpatialType must be called only with spatial types"); // Note that we made sure that payload type detection will not return spatial for <V3 payloads // So the only way we can get a spatial type reference is if it comes from the model, // in which case we want to fail for <V3 payloads, since we can't report spatial values from such payloads. ODataVersionChecker.CheckSpatialValue(inputContext.Version); // Spatial value can be either null constant or a JSON object // If it's a null primitive value, report a null value. if (!insideJsonObjectValue && TryReadNullValue(jsonReader, inputContext, expectedValueTypeReference, validateNullValue, propertyName)) { return(null); } System.Spatial.ISpatial spatialValue = null; if (insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject) { IDictionary <string, object> jsonObject = ReadObjectValue(jsonReader, insideJsonObjectValue, inputContext, recursionDepth); System.Spatial.GeoJsonObjectFormatter jsonObjectFormatter = System.Spatial.SpatialImplementation.CurrentImplementation.CreateGeoJsonObjectFormatter(); if (EdmLibraryExtensions.IsGeographyType(expectedValueTypeReference)) { spatialValue = jsonObjectFormatter.Read <System.Spatial.Geography>(jsonObject); } else { spatialValue = jsonObjectFormatter.Read <System.Spatial.Geometry>(jsonObject); } } if (spatialValue == null) { throw new ODataException(ODataErrorStrings.ODataJsonReaderCoreUtils_CannotReadSpatialPropertyValue); } return(spatialValue); }
/// <summary> /// Try and parse spatial type from the json payload. /// </summary> /// <param name="jsonReader">The JSON reader to read from.</param> /// <param name="insideJsonObjectValue">true if the reader is positioned on the first property of the value which is a JSON Object /// (or the second property if the first one was odata.type).</param> /// <param name="inputContext">The input context with all the settings.</param> /// <param name="expectedValueTypeReference">Expected edm property type.</param> /// <param name="validateNullValue">true to validate null values; otherwise false.</param> /// <param name="recursionDepth">The recursion depth to start with.</param> /// <param name="propertyName">The name of the property whose value is being read, if applicable (used for error reporting).</param> /// <returns>An instance of the spatial type.</returns> internal static async Task <ISpatial> ReadSpatialValueAsync( IJsonReaderAsync jsonReader, bool insideJsonObjectValue, ODataInputContext inputContext, IEdmPrimitiveTypeReference expectedValueTypeReference, bool validateNullValue, int recursionDepth, string propertyName) { Debug.Assert(jsonReader != null, "jsonReader != null"); Debug.Assert(inputContext != null, "inputContext != null"); Debug.Assert(expectedValueTypeReference != null, "expectedValueTypeReference != null"); Debug.Assert(expectedValueTypeReference.IsSpatial(), "TryParseSpatialType must be called only with spatial types"); // Spatial value can be either null constant or a JSON object // If it's a null primitive value, report a null value. if (!insideJsonObjectValue && await TryReadNullValueAsync(jsonReader, inputContext, expectedValueTypeReference, validateNullValue, propertyName) .ConfigureAwait(false)) { return(null); } ISpatial spatialValue = null; if (insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject) { Dictionary <string, object> jsonObject = await ReadObjectValueAsync(jsonReader, insideJsonObjectValue, inputContext, recursionDepth) .ConfigureAwait(false); GeoJsonObjectFormatter jsonObjectFormatter = SpatialImplementation.CurrentImplementation.CreateGeoJsonObjectFormatter(); if (expectedValueTypeReference.IsGeography()) { spatialValue = jsonObjectFormatter.Read <Geography>(jsonObject); } else { spatialValue = jsonObjectFormatter.Read <Geometry>(jsonObject); } } if (spatialValue == null) { throw new ODataException(ODataErrorStrings.ODataJsonReaderCoreUtils_CannotReadSpatialPropertyValue); } return(spatialValue); }
/// <summary> /// Try and parse spatial type from the json payload. /// </summary> /// <param name="jsonReader">The JSON reader to read from.</param> /// <param name="insideJsonObjectValue">true if the reader is positioned on the first property of the value which is a JSON Object /// (or the second property if the first one was odata.type).</param> /// <param name="inputContext">The input context with all the settings.</param> /// <param name="expectedValueTypeReference">Expected edm property type.</param> /// <param name="validateNullValue">true to validate null values; otherwise false.</param> /// <param name="recursionDepth">The recursion depth to start with.</param> /// <param name="propertyName">The name of the property whose value is being read, if applicable (used for error reporting).</param> /// <returns>An instance of the spatial type.</returns> internal static ISpatial ReadSpatialValue( BufferingJsonReader jsonReader, bool insideJsonObjectValue, ODataInputContext inputContext, IEdmPrimitiveTypeReference expectedValueTypeReference, bool validateNullValue, int recursionDepth, string propertyName) { Debug.Assert(jsonReader != null, "jsonReader != null"); Debug.Assert(inputContext != null, "inputContext != null"); Debug.Assert(expectedValueTypeReference != null, "expectedValueTypeReference != null"); Debug.Assert(expectedValueTypeReference.IsSpatial(), "TryParseSpatialType must be called only with spatial types"); // Spatial value can be either null constant or a JSON object // If it's a null primitive value, report a null value. if (!insideJsonObjectValue && TryReadNullValue(jsonReader, inputContext, expectedValueTypeReference, validateNullValue, propertyName)) { return null; } Microsoft.Spatial.ISpatial spatialValue = null; if (insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject) { IDictionary<string, object> jsonObject = ReadObjectValue(jsonReader, insideJsonObjectValue, inputContext, recursionDepth); Microsoft.Spatial.GeoJsonObjectFormatter jsonObjectFormatter = Microsoft.Spatial.SpatialImplementation.CurrentImplementation.CreateGeoJsonObjectFormatter(); if (EdmLibraryExtensions.IsGeographyType(expectedValueTypeReference)) { spatialValue = jsonObjectFormatter.Read<Microsoft.Spatial.Geography>(jsonObject); } else { spatialValue = jsonObjectFormatter.Read<Microsoft.Spatial.Geometry>(jsonObject); } } if (spatialValue == null) { throw new ODataException(ODataErrorStrings.ODataJsonReaderCoreUtils_CannotReadSpatialPropertyValue); } return spatialValue; }
/// <summary> /// Try and parse spatial type from the json payload. /// </summary> /// <param name="jsonReader">The JSON reader to read from.</param> /// <param name="insideJsonObjectValue">true if the reader is positioned on the first property of the value which is a JSON Object /// (or the second property if the first one was odata.type).</param> /// <param name="inputContext">The input context with all the settings.</param> /// <param name="expectedValueTypeReference">Expected edm property type.</param> /// <param name="validateNullValue">true to validate null values; otherwise false.</param> /// <param name="recursionDepth">The recursion depth to start with.</param> /// <param name="propertyName">The name of the property whose value is being read, if applicable (used for error reporting).</param> /// <returns>An instance of the spatial type.</returns> internal static ISpatial ReadSpatialValue( BufferingJsonReader jsonReader, bool insideJsonObjectValue, ODataInputContext inputContext, IEdmPrimitiveTypeReference expectedValueTypeReference, bool validateNullValue, int recursionDepth, string propertyName) { Debug.Assert(jsonReader != null, "jsonReader != null"); Debug.Assert(inputContext != null, "inputContext != null"); Debug.Assert(expectedValueTypeReference != null, "expectedValueTypeReference != null"); Debug.Assert(expectedValueTypeReference.IsSpatial(), "TryParseSpatialType must be called only with spatial types"); // Spatial value can be either null constant or a JSON object // If it's a null primitive value, report a null value. if (!insideJsonObjectValue && TryReadNullValue(jsonReader, inputContext, expectedValueTypeReference, validateNullValue, propertyName)) { return(null); } Microsoft.Spatial.ISpatial spatialValue = null; if (insideJsonObjectValue || jsonReader.NodeType == JsonNodeType.StartObject) { IDictionary <string, object> jsonObject = ReadObjectValue(jsonReader, insideJsonObjectValue, inputContext, recursionDepth); Microsoft.Spatial.GeoJsonObjectFormatter jsonObjectFormatter = Microsoft.Spatial.SpatialImplementation.CurrentImplementation.CreateGeoJsonObjectFormatter(); if (EdmLibraryExtensions.IsGeographyType(expectedValueTypeReference)) { spatialValue = jsonObjectFormatter.Read <Microsoft.Spatial.Geography>(jsonObject); } else { spatialValue = jsonObjectFormatter.Read <Microsoft.Spatial.Geometry>(jsonObject); } } if (spatialValue == null) { throw new ODataException(ODataErrorStrings.ODataJsonReaderCoreUtils_CannotReadSpatialPropertyValue); } return(spatialValue); }
/// <summary> /// Writes a primitive value. /// Uses a registered primitive type converter to write the value if one is registered for the type, otherwise directly writes the value. /// </summary> /// <param name="value">The value to write.</param> /// <param name="expectedTypeReference">The expected type reference of the primitive value.</param> public void WritePrimitiveValue( object value, IEdmTypeReference expectedTypeReference) { Debug.Assert(value != null, "value != null"); IEdmPrimitiveTypeReference actualTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (expectedTypeReference != null) { ValidationUtils.ValidateIsExpectedPrimitiveType(value, actualTypeReference, expectedTypeReference); } if (actualTypeReference != null && actualTypeReference.IsSpatial()) { PrimitiveConverter.Instance.WriteJsonLight(value, this.JsonWriter); } else { this.JsonWriter.WritePrimitiveValue(value); } }
/// <summary> /// Reads a primitive value. /// </summary> /// <param name="expectedValueTypeReference">The expected type reference of the value.</param> /// <param name="validateNullValue">true to validate null values; otherwise false.</param> /// <param name="propertyName">The name of the property whose value is being read, if applicable (used for error reporting).</param> /// <returns>The value of the primitive value.</returns> /// <remarks> /// Pre-Condition: none - Fails if the current node is not a JsonNodeType.PrimitiveValue /// Post-Condition: almost anything - the node after the primitive value. /// /// Made internal only for testability. /// </remarks> internal object ReadPrimitiveValue(IEdmPrimitiveTypeReference expectedValueTypeReference, bool validateNullValue, string propertyName) { DebugUtils.CheckNoExternalCallers(); this.JsonReader.AssertNotBuffering(); object result; if (expectedValueTypeReference != null && expectedValueTypeReference.IsSpatial()) { result = ODataJsonReaderCoreUtils.ReadSpatialValue( this.JsonReader, /*insideJsonObjectValue*/ false, this.VerboseJsonInputContext, expectedValueTypeReference, validateNullValue, this.recursionDepth, propertyName); } else { result = this.JsonReader.ReadPrimitiveValue(); if (expectedValueTypeReference != null && !this.MessageReaderSettings.DisablePrimitiveTypeConversion) { result = ODataVerboseJsonReaderUtils.ConvertValue( result, expectedValueTypeReference, this.MessageReaderSettings, this.Version, validateNullValue, propertyName); } } this.JsonReader.AssertNotBuffering(); return(result); }
/// <summary> /// Writes a primitive value. /// Uses a registered primitive type converter to write the value if one is registered for the type, otherwise directly writes the value. /// </summary> /// <param name="value">The value to write.</param> /// <param name="collectionValidator">The collection validator instance.</param> /// <param name="expectedTypeReference">The expected type reference of the primitive value.</param> internal void WritePrimitiveValue( object value, CollectionWithoutExpectedTypeValidator collectionValidator, IEdmTypeReference expectedTypeReference) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(value != null, "value != null"); IEdmPrimitiveTypeReference actualTypeReference = EdmLibraryExtensions.GetPrimitiveTypeReference(value.GetType()); if (collectionValidator != null) { if (actualTypeReference == null) { throw new ODataException(o.Strings.ValidationUtils_UnsupportedPrimitiveType(value.GetType().FullName)); } collectionValidator.ValidateCollectionItem(actualTypeReference.FullName(), EdmTypeKind.Primitive); } if (expectedTypeReference != null) { ValidationUtils.ValidateIsExpectedPrimitiveType(value, actualTypeReference, expectedTypeReference); } if (actualTypeReference != null && actualTypeReference.IsSpatial()) { // For spatial types, we will always write the type name. This is consistent with complex types. string typeName = actualTypeReference.FullName(); PrimitiveConverter.Instance.WriteJson(value, this.JsonWriter, typeName, this.Version); } else { this.JsonWriter.WritePrimitiveValue(value, this.Version); } }
private object ReadPrimitiveValueImplementation(IEdmPrimitiveTypeReference expectedValueTypeReference, bool validateNullValue) { if ((expectedValueTypeReference != null) && expectedValueTypeReference.IsSpatial()) { return this.ReadSpatialValue(expectedValueTypeReference, validateNullValue); } object obj2 = base.JsonReader.ReadPrimitiveValue(); if ((expectedValueTypeReference != null) && !base.MessageReaderSettings.DisablePrimitiveTypeConversion) { obj2 = ODataJsonReaderUtils.ConvertValue(obj2, expectedValueTypeReference, base.MessageReaderSettings, base.Version, validateNullValue); } return obj2; }
/// <summary> /// Reads a primitive, complex or collection value. /// </summary> /// <param name="expectedTypeReference">The expected type reference of the property value.</param> /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use - if null the method should create a new one if necessary.</param> /// <param name="collectionValidator">The collection validator instance if no expected item type has been specified; otherwise null.</param> /// <param name="validateNullValue">true to validate null values; otherwise false.</param> /// <param name="propertyName">The name of the property whose value is being read, if applicable.</param> /// <returns>The value of the property read.</returns> /// <remarks> /// Pre-Condition: JsonNodeType.PrimitiveValue - the value of the property is a primitive value /// JsonNodeType.StartObject - the value of the property is an object /// JsonNodeType.StartArray - the value of the property is an array - method will fail in this case. /// Post-Condition: almost anything - the node after the property value. /// /// Returns the value of the property read, which can be one of: /// - null /// - primitive value /// - <see cref="ODataComplexValue"/> /// - <see cref="ODataCollectionValue"/> /// </remarks> private object ReadNonEntityValueImplementation( IEdmTypeReference expectedTypeReference, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, CollectionWithoutExpectedTypeValidator collectionValidator, bool validateNullValue, string propertyName) { DebugUtils.CheckNoExternalCallers(); Debug.Assert( this.JsonReader.NodeType == JsonNodeType.PrimitiveValue || this.JsonReader.NodeType == JsonNodeType.StartObject || this.JsonReader.NodeType == JsonNodeType.StartArray, "Pre-Condition: expected JsonNodeType.PrimitiveValue or JsonNodeType.StartObject or JsonNodeType.StartArray"); Debug.Assert( expectedTypeReference == null || !expectedTypeReference.IsODataEntityTypeKind(), "Only primitive, complex or collection types can be read by this method."); Debug.Assert( expectedTypeReference == null || collectionValidator == null, "If an expected value type reference is specified, no collection validator must be provided."); this.JsonReader.AssertNotBuffering(); // Property values can be only primitives or objects. No property can have a JSON array value. JsonNodeType nodeType = this.JsonReader.NodeType; if (nodeType == JsonNodeType.StartArray) { throw new ODataException(ODataErrorStrings.ODataJsonPropertyAndValueDeserializer_CannotReadPropertyValue(nodeType)); } // Try to read a null value object result; if (ODataJsonReaderCoreUtils.TryReadNullValue( this.JsonReader, this.VerboseJsonInputContext, expectedTypeReference, validateNullValue, propertyName)) { result = null; } else { // Read the payload type name string payloadTypeName = this.FindTypeNameInPayload(); SerializationTypeNameAnnotation serializationTypeNameAnnotation; EdmTypeKind targetTypeKind; IEdmTypeReference targetTypeReference = ReaderValidationUtils.ResolvePayloadTypeNameAndComputeTargetType( EdmTypeKind.None, /*defaultPrimitivePayloadType*/ null, expectedTypeReference, payloadTypeName, this.Model, this.MessageReaderSettings, this.Version, this.GetNonEntityValueKind, out targetTypeKind, out serializationTypeNameAnnotation); switch (targetTypeKind) { case EdmTypeKind.Primitive: Debug.Assert(targetTypeReference == null || targetTypeReference.IsODataPrimitiveTypeKind(), "Expected an OData primitive type."); IEdmPrimitiveTypeReference primitiveTargetTypeReference = targetTypeReference == null ? null : targetTypeReference.AsPrimitive(); if (payloadTypeName != null && !primitiveTargetTypeReference.IsSpatial()) { throw new ODataException(ODataErrorStrings.ODataJsonPropertyAndValueDeserializer_InvalidPrimitiveTypeName(payloadTypeName)); } result = this.ReadPrimitiveValue( primitiveTargetTypeReference, validateNullValue, propertyName); break; case EdmTypeKind.Complex: Debug.Assert(targetTypeReference == null || targetTypeReference.IsComplex(), "Expected a complex type."); result = this.ReadComplexValueImplementation( targetTypeReference == null ? null : targetTypeReference.AsComplex(), payloadTypeName, serializationTypeNameAnnotation, duplicatePropertyNamesChecker); break; case EdmTypeKind.Collection: Debug.Assert(this.Version >= ODataVersion.V3, "Type resolution should already fail if we would decide to read a collection value in V1/V2 payload."); IEdmCollectionTypeReference collectionTypeReference = ValidationUtils.ValidateCollectionType(targetTypeReference); result = this.ReadCollectionValueImplementation( collectionTypeReference, payloadTypeName, serializationTypeNameAnnotation); break; default: throw new ODataException(ODataErrorStrings.General_InternalError(InternalErrorCodes.ODataVerboseJsonPropertyAndValueDeserializer_ReadPropertyValue)); } // If we have no expected type make sure the collection items are of the same kind and specify the same name. if (collectionValidator != null) { string payloadTypeNameFromResult = ODataVerboseJsonReaderUtils.GetPayloadTypeName(result); Debug.Assert(expectedTypeReference == null, "If a collection validator is specified there must not be an expected value type reference."); collectionValidator.ValidateCollectionItem(payloadTypeNameFromResult, targetTypeKind); } } this.JsonReader.AssertNotBuffering(); return(result); }
/// <summary> /// Try and parse spatial type from the json payload. /// </summary> /// <param name="expectedValueTypeReference">Expected edm property type.</param> /// <param name="validateNullValue">true to validate null values; otherwise false.</param> /// <returns>An instance of the spatial type.</returns> private System.Spatial.ISpatial ReadSpatialValue(IEdmPrimitiveTypeReference expectedValueTypeReference, bool validateNullValue) { Debug.Assert(expectedValueTypeReference != null, "expectedValueTypeReference != null"); Debug.Assert(expectedValueTypeReference.IsSpatial(), "TryParseSpatialType must be called only with spatial types"); // Note that we made sure that payload type detection will not return spatial for <V3 payloads // So the only way we can get a spatial type reference is if it comes from the model, // in which case we want to fail for <V3 payloads, since we can't report spatial values from such payloads. ODataVersionChecker.CheckSpatialValue(this.Version); // Spatial value can be either null constant or a JSON object // If it's a null primitive value, report a null value. if (this.TryReadNullValue(expectedValueTypeReference, validateNullValue)) { return null; } System.Spatial.ISpatial spatialValue = null; if (this.JsonReader.NodeType == JsonNodeType.StartObject) { IDictionary<string, object> jsonObject = this.ReadObjectValue(this.JsonReader); System.Spatial.GeoJsonObjectFormatter jsonObjectFormatter = System.Spatial.SpatialImplementation.CurrentImplementation.CreateGeoJsonObjectFormatter(); if (EdmLibraryExtensions.IsGeographyType(expectedValueTypeReference)) { spatialValue = jsonObjectFormatter.Read<System.Spatial.Geography>(jsonObject); } else { spatialValue = jsonObjectFormatter.Read<System.Spatial.Geometry>(jsonObject); } } if (spatialValue == null) { throw new ODataException(o.Strings.ODataJsonPropertyAndValueDeserializer_CannotReadSpatialPropertyValue); } return spatialValue; }
/// <summary> /// Reads a primitive value. /// </summary> /// <param name="insideJsonObjectValue">true if the reader is positioned on the first property of the value which is a JSON Object /// (or the second property if the first one was odata.type).</param> /// <param name="expectedValueTypeReference">The expected type reference of the value, or null if none is available.</param> /// <param name="validateNullValue">true to validate null values; otherwise false.</param> /// <param name="propertyName">The name of the property whose value is being read, if applicable (used for error reporting).</param> /// <returns>The value of the primitive value.</returns> /// <remarks> /// Pre-Condition: insideJsonObjectValue == false -> none - Fails if the current node is not a JsonNodeType.PrimitiveValue /// insideJsonObjectValue == true -> JsonNodeType.Property or JsonNodeType.EndObject - the first property of the value object, /// or the second property if first was odata.type, or the end-object. /// Post-Condition: almost anything - the node after the primitive value. /// </remarks> private object ReadPrimitiveValue(bool insideJsonObjectValue, IEdmPrimitiveTypeReference expectedValueTypeReference, bool validateNullValue, string propertyName) { object result; if (expectedValueTypeReference != null && expectedValueTypeReference.IsSpatial()) { result = ODataJsonReaderCoreUtils.ReadSpatialValue( this.JsonReader, insideJsonObjectValue, this.JsonLightInputContext, expectedValueTypeReference, validateNullValue, this.recursionDepth, propertyName); } else { if (insideJsonObjectValue) { // We manually throw JSON exception here to get a nicer error message (we expect primitive value and got object). // Otherwise the ReadPrimitiveValue would fail with something like "expected primitive value but found property/end object" which is rather confusing. throw new ODataException(ODataErrorStrings.JsonReaderExtensions_UnexpectedNodeDetectedWithPropertyName(JsonNodeType.PrimitiveValue, JsonNodeType.StartObject, propertyName)); } result = this.JsonReader.ReadPrimitiveValue(); if (expectedValueTypeReference != null) { if ((expectedValueTypeReference.IsDecimal() || expectedValueTypeReference.IsInt64()) && result != null) { if ((result is string) ^ this.JsonReader.IsIeee754Compatible) { throw new ODataException(ODataErrorStrings.ODataJsonReaderUtils_ConflictBetweenInputFormatAndParameter(expectedValueTypeReference.FullName())); } } result = ODataJsonLightReaderUtils.ConvertValue( result, expectedValueTypeReference, this.MessageReaderSettings, validateNullValue, propertyName, this.Model.GetPayloadValueConverter()); } else { if (result is Decimal) { // convert decimal back to double to follow legacy logic when target type is not specified and IEEE754Compatible=false. // we may lose precision for some range of int64 and decimal. return Convert.ToDouble((Decimal)result); } } } return result; }
/// <summary> /// Reads a primitive value. /// </summary> /// <param name="expectedValueTypeReference">The expected type reference of the value.</param> /// <param name="validateNullValue">true to validate null values; otherwise false.</param> /// <returns>The value of the primitive value.</returns> /// <remarks> /// Pre-Condition: none - Fails if the current node is not a JsonNodeType.PrimitiveValue /// Post-Condition: almost anything - the node after the primitive value. /// </remarks> private object ReadPrimitiveValueImplementation(IEdmPrimitiveTypeReference expectedValueTypeReference, bool validateNullValue) { this.JsonReader.AssertNotBuffering(); object result; if (expectedValueTypeReference != null && expectedValueTypeReference.IsSpatial()) { result = this.ReadSpatialValue(expectedValueTypeReference, validateNullValue); } else { result = this.JsonReader.ReadPrimitiveValue(); if (expectedValueTypeReference != null && !this.MessageReaderSettings.DisablePrimitiveTypeConversion) { result = ODataJsonReaderUtils.ConvertValue(result, expectedValueTypeReference, this.MessageReaderSettings, this.Version, validateNullValue); } } this.JsonReader.AssertNotBuffering(); return result; }