public LazyCosmosArray( IJsonNavigator jsonNavigator, IJsonNavigatorNode jsonNavigatorNode) { JsonNodeType type = jsonNavigator.GetNodeType(jsonNavigatorNode); if (type != JsonNodeType.Array) { throw new ArgumentOutOfRangeException($"{nameof(jsonNavigatorNode)} must be an {JsonNodeType.Array} node. Got {type} instead."); } this.jsonNavigator = jsonNavigator; this.jsonNavigatorNode = jsonNavigatorNode; this.lazyCosmosElementArray = new Lazy <Lazy <CosmosElement>[]>(() => { Lazy <CosmosElement>[] lazyArray = new Lazy <CosmosElement> [this.jsonNavigator.GetArrayItemCount(this.jsonNavigatorNode)]; int index = 0; // Using foreach instead of indexer, since the navigator doesn't support random seeks efficiently. foreach (IJsonNavigatorNode arrayItem in this.jsonNavigator.GetArrayItems(this.jsonNavigatorNode)) { lazyArray[index] = new Lazy <CosmosElement>(() => CosmosElement.Dispatch(this.jsonNavigator, arrayItem)); index++; } return(lazyArray); }); }
public LazyCosmosObject(IJsonNavigator jsonNavigator, IJsonNavigatorNode jsonNavigatorNode) { JsonNodeType type = jsonNavigator.GetNodeType(jsonNavigatorNode); if (type != JsonNodeType.Object) { throw new ArgumentOutOfRangeException($"{nameof(jsonNavigatorNode)} must be a {JsonNodeType.Object} node. Got {type} instead."); } this.jsonNavigator = jsonNavigator; this.jsonNavigatorNode = jsonNavigatorNode; this.lazyCache = new Lazy <Dictionary <string, CosmosElement> >(() => { int propertyCount = this.jsonNavigator.GetObjectPropertyCount(this.jsonNavigatorNode); Dictionary <string, CosmosElement> cache = new Dictionary <string, CosmosElement>(capacity: propertyCount); foreach (ObjectProperty objectProperty in this.jsonNavigator.GetObjectProperties(this.jsonNavigatorNode)) { string key = this.jsonNavigator.GetStringValue(objectProperty.NameNode); CosmosElement value = CosmosElement.Dispatch(this.jsonNavigator, objectProperty.ValueNode); cache[key] = value; } return(cache); }); }
public static CosmosElement Create(byte[] buffer) { IJsonNavigator jsonNavigator = JsonNavigator.Create(buffer); IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode(); return(CosmosElement.Dispatch(jsonNavigator, jsonNavigatorNode)); }
public static TryCatch <TCosmosElement> CreateFromBuffer <TCosmosElement>(ReadOnlyMemory <byte> buffer) where TCosmosElement : CosmosElement { if (buffer.IsEmpty) { TryCatch <TCosmosElement> .FromException( new ArgumentException($"{nameof(buffer)} must not be empty.")); } CosmosElement unTypedCosmosElement; try { IJsonNavigator jsonNavigator = JsonNavigator.Create(buffer); IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode(); unTypedCosmosElement = CosmosElement.Dispatch(jsonNavigator, jsonNavigatorNode); } catch (JsonParseException jpe) { return(TryCatch <TCosmosElement> .FromException(jpe)); } if (!(unTypedCosmosElement is TCosmosElement typedCosmosElement)) { return(TryCatch <TCosmosElement> .FromException( new CosmosElementWrongTypeException( message : $"buffer was incorrect cosmos element type: {unTypedCosmosElement.GetType()} when {typeof(TCosmosElement)} was requested."))); } return(TryCatch <TCosmosElement> .FromResult(typedCosmosElement)); }
public override bool TryGetValue(string key, out CosmosElement value) { if (this.cachedElements.TryGetValue( key, out CosmosElement cosmosElemet)) { value = cosmosElemet; return(true); } if (this.jsonNavigator.TryGetObjectProperty( this.jsonNavigatorNode, key, out ObjectProperty objectProperty)) { value = CosmosElement.Dispatch(this.jsonNavigator, objectProperty.ValueNode); this.cachedElements[key] = value; return(true); } #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. value = default; // Dictionary.TryGetValue does not use nullable references. #pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. return(false); }
public static CosmosElement CreateFromBuffer(ReadOnlyMemory <byte> buffer) { IJsonNavigator jsonNavigator = JsonNavigator.Create(buffer); IJsonNavigatorNode jsonNavigatorNode = jsonNavigator.GetRootNode(); return(CosmosElement.Dispatch(jsonNavigator, jsonNavigatorNode)); }
public override bool TryGetValue(string key, out CosmosElement value) { value = default; bool gotValue; if (this.cachedElements.TryGetValue( key, out CosmosElement cosmosElemet)) { value = cosmosElemet; gotValue = true; } else if (this.jsonNavigator.TryGetObjectProperty( this.jsonNavigatorNode, key, out ObjectProperty objectProperty)) { value = CosmosElement.Dispatch(this.jsonNavigator, objectProperty.ValueNode); gotValue = true; this.cachedElements[key] = value; } else { value = null; gotValue = false; } return(gotValue); }
public override CosmosElement this[int index] { get { IJsonNavigatorNode arrayItemNode = this.jsonNavigator.GetArrayItemAt(this.jsonNavigatorNode, index); return(CosmosElement.Dispatch(this.jsonNavigator, arrayItemNode)); } }
public override IEnumerator <KeyValuePair <string, CosmosElement> > GetEnumerator() => this .jsonNavigator .GetObjectProperties(this.jsonNavigatorNode) .Select( (objectProperty) => new KeyValuePair <string, CosmosElement>( this.jsonNavigator.GetStringValue(objectProperty.NameNode), CosmosElement.Dispatch(this.jsonNavigator, objectProperty.ValueNode))) .GetEnumerator();
public override bool TryGetValue(string key, out CosmosElement value) { if (this.cachedElements.TryGetValue( key, out CosmosElement cosmosElemet)) { value = cosmosElemet; return(true); } if (this.jsonNavigator.TryGetObjectProperty( this.jsonNavigatorNode, key, out ObjectProperty objectProperty)) { value = CosmosElement.Dispatch(this.jsonNavigator, objectProperty.ValueNode); this.cachedElements[key] = value; return(true); } value = default; return(false); }
/// <summary> /// Converts a list of CosmosElements into a memory stream. /// </summary> /// <param name="memoryStream">The memory stream response from Azure Cosmos</param> /// <param name="resourceType">The resource type</param> /// <param name="cosmosSerializationOptions">The custom serialization options. This allows custom serialization types like BSON, JSON, or other formats</param> /// <returns>Returns a memory stream of cosmos elements. By default the memory stream will contain JSON.</returns> internal static CosmosArray ToCosmosElements( MemoryStream memoryStream, ResourceType resourceType, CosmosSerializationFormatOptions cosmosSerializationOptions = null) { if (!memoryStream.CanRead) { throw new InvalidDataException("Stream can not be read"); } // Execute the callback an each element of the page // For example just could get a response like this // { // "_rid": "qHVdAImeKAQ=", // "Documents": [{ // "id": "03230", // "_rid": "qHVdAImeKAQBAAAAAAAAAA==", // "_self": "dbs\/qHVdAA==\/colls\/qHVdAImeKAQ=\/docs\/qHVdAImeKAQBAAAAAAAAAA==\/", // "_etag": "\"410000b0-0000-0000-0000-597916b00000\"", // "_attachments": "attachments\/", // "_ts": 1501107886 // }], // "_count": 1 // } // And you should execute the callback on each document in "Documents". long responseLengthBytes = memoryStream.Length; ReadOnlyMemory <byte> content; if (memoryStream.TryGetBuffer(out ArraySegment <byte> buffer)) { content = buffer; } else { content = memoryStream.ToArray(); } IJsonNavigator jsonNavigator; // Use the users custom navigator if (cosmosSerializationOptions != null) { jsonNavigator = cosmosSerializationOptions.CreateCustomNavigatorCallback(content); if (jsonNavigator == null) { throw new InvalidOperationException("The CosmosSerializationOptions did not return a JSON navigator."); } } else { jsonNavigator = JsonNavigator.Create(content); } string resourceName = CosmosElementSerializer.GetRootNodeName(resourceType); CosmosArray documents; if ((jsonNavigator.SerializationFormat == JsonSerializationFormat.Binary) && jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), "stringDictionary", out ObjectProperty stringDictionaryProperty)) { // Payload is string dictionary encode so we have to decode using the string dictionary. IJsonNavigatorNode stringDictionaryNode = stringDictionaryProperty.ValueNode; JsonStringDictionary jsonStringDictionary = JsonStringDictionary.CreateFromStringArray( jsonNavigator .GetArrayItems(stringDictionaryNode) .Select(item => jsonNavigator.GetStringValue(item)) .ToList()); if (!jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), resourceName, out ObjectProperty resourceProperty)) { throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}"); } IJsonNavigatorNode resources = resourceProperty.ValueNode; if (!jsonNavigator.TryGetBufferedBinaryValue(resources, out ReadOnlyMemory <byte> resourceBinary)) { resourceBinary = jsonNavigator.GetBinaryValue(resources); } IJsonNavigator navigatorWithStringDictionary = JsonNavigator.Create(resourceBinary, jsonStringDictionary); if (!(CosmosElement.Dispatch( navigatorWithStringDictionary, navigatorWithStringDictionary.GetRootNode()) is CosmosArray cosmosArray)) { throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}"); } documents = cosmosArray; } else { // Payload is not string dictionary encoded so we can just do for the documents as is. if (!jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), resourceName, out ObjectProperty objectProperty)) { throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}"); } if (!(CosmosElement.Dispatch( jsonNavigator, objectProperty.ValueNode) is CosmosArray cosmosArray)) { throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}"); } documents = cosmosArray; } return(documents); }
/// <summary> /// Converts a list of CosmosElements into a memory stream. /// </summary> /// <param name="memoryStream">The memory stream response from Azure Cosmos</param> /// <param name="resourceType">The resource type</param> /// <param name="cosmosSerializationOptions">The custom serialization options. This allows custom serialization types like BSON, JSON, or other formats</param> /// <returns>Returns a memory stream of cosmos elements. By default the memory stream will contain JSON.</returns> internal static CosmosArray ToCosmosElements( MemoryStream memoryStream, ResourceType resourceType, CosmosSerializationOptions cosmosSerializationOptions = null) { if (!memoryStream.CanRead) { throw new InvalidDataException("Stream can not be read"); } // Execute the callback an each element of the page // For example just could get a response like this // { // "_rid": "qHVdAImeKAQ=", // "Documents": [{ // "id": "03230", // "_rid": "qHVdAImeKAQBAAAAAAAAAA==", // "_self": "dbs\/qHVdAA==\/colls\/qHVdAImeKAQ=\/docs\/qHVdAImeKAQBAAAAAAAAAA==\/", // "_etag": "\"410000b0-0000-0000-0000-597916b00000\"", // "_attachments": "attachments\/", // "_ts": 1501107886 // }], // "_count": 1 // } // And you should execute the callback on each document in "Documents". long responseLengthBytes = memoryStream.Length; byte[] content = memoryStream.ToArray(); IJsonNavigator jsonNavigator = null; // Use the users custom navigator if (cosmosSerializationOptions != null) { jsonNavigator = cosmosSerializationOptions.CreateCustomNavigatorCallback(content); if (jsonNavigator == null) { throw new InvalidOperationException("The CosmosSerializationOptions did not return a JSON navigator."); } } else { jsonNavigator = JsonNavigator.Create(content); } string resourceName = CosmosElementSerializer.GetRootNodeName(resourceType); if (!jsonNavigator.TryGetObjectProperty( jsonNavigator.GetRootNode(), resourceName, out ObjectProperty objectProperty)) { throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}"); } IJsonNavigatorNode cosmosElements = objectProperty.ValueNode; if (!(CosmosElement.Dispatch( jsonNavigator, cosmosElements) is CosmosArray cosmosArray)) { throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}"); } return(cosmosArray); }
public override IEnumerator <CosmosElement> GetEnumerator() => this .jsonNavigator .GetArrayItems(this.jsonNavigatorNode) .Select((arrayItem) => CosmosElement.Dispatch(this.jsonNavigator, arrayItem)) .GetEnumerator();