internal static JsonTokenInfo[] GetTokensFromNode(IJsonNavigatorNode node, IJsonNavigator navigator, bool performCorrectnessCheck)
        {
            switch (navigator.GetNodeType(node))
            {
            case JsonNodeType.Null:
                return(new JsonTokenInfo[] { JsonTokenInfo.Null() });

            case JsonNodeType.False:
                return(new JsonTokenInfo[] { JsonTokenInfo.Boolean(false) });

            case JsonNodeType.True:
                return(new JsonTokenInfo[] { JsonTokenInfo.Boolean(true) });

            case JsonNodeType.Number:
                return(new JsonTokenInfo[] { JsonTokenInfo.Number(navigator.GetNumberValue(node)) });

            case JsonNodeType.String:
                return(new JsonTokenInfo[] { JsonTokenInfo.String(navigator.GetStringValue(node)) });

            case JsonNodeType.Array:
                return(JsonNavigatorTests.GetTokensFromArrayNode(node, navigator, performCorrectnessCheck));

            case JsonNodeType.Object:
                return(JsonNavigatorTests.GetTokensFromObjectNode(node, navigator, performCorrectnessCheck));

            case JsonNodeType.FieldName:
                return(new JsonTokenInfo[] { JsonTokenInfo.FieldName(navigator.GetStringValue(node)) });

            default:
                throw new InvalidOperationException();
            }
        }
Exemple #2
0
        private static JsonToken[] GetTokensFromNode(IJsonNavigatorNode node, IJsonNavigator navigator, bool performCorrectnessCheck)
        {
            switch (navigator.GetNodeType(node))
            {
            case JsonNodeType.Null:
                return(new JsonToken[] { JsonToken.Null() });

            case JsonNodeType.False:
                return(new JsonToken[] { JsonToken.Boolean(false) });

            case JsonNodeType.True:
                return(new JsonToken[] { JsonToken.Boolean(true) });

            case JsonNodeType.Number64:
                return(new JsonToken[] { JsonToken.Number(navigator.GetNumber64Value(node)) });

            case JsonNodeType.String:
                return(new JsonToken[] { JsonToken.String(navigator.GetStringValue(node)) });

            case JsonNodeType.Array:
                return(JsonNavigatorTests.GetTokensFromArrayNode(node, navigator, performCorrectnessCheck));

            case JsonNodeType.Object:
                return(JsonNavigatorTests.GetTokensFromObjectNode(node, navigator, performCorrectnessCheck));

            case JsonNodeType.FieldName:
                return(new JsonToken[] { JsonToken.FieldName(navigator.GetStringValue(node)) });

            case JsonNodeType.Int8:
                return(new JsonToken[] { JsonToken.Int8(navigator.GetInt8Value(node)) });

            case JsonNodeType.Int16:
                return(new JsonToken[] { JsonToken.Int16(navigator.GetInt16Value(node)) });

            case JsonNodeType.Int32:
                return(new JsonToken[] { JsonToken.Int32(navigator.GetInt32Value(node)) });

            case JsonNodeType.Int64:
                return(new JsonToken[] { JsonToken.Int64(navigator.GetInt64Value(node)) });

            case JsonNodeType.UInt32:
                return(new JsonToken[] { JsonToken.UInt32(navigator.GetUInt32Value(node)) });

            case JsonNodeType.Float32:
                return(new JsonToken[] { JsonToken.Float32(navigator.GetFloat32Value(node)) });

            case JsonNodeType.Float64:
                return(new JsonToken[] { JsonToken.Float64(navigator.GetFloat64Value(node)) });

            case JsonNodeType.Guid:
                return(new JsonToken[] { JsonToken.Guid(navigator.GetGuidValue(node)) });

            case JsonNodeType.Binary:
                return(new JsonToken[] { JsonToken.Binary(navigator.GetBinaryValue(node)) });

            default:
                throw new InvalidOperationException();
            }
        }
        public void LargeArrayBinaryJsonTest()
        {
            StringBuilder builder = new StringBuilder((1 << 24) + 50);

            builder.Append('[');
            for (int x = 1 << 24; x < (1 << 24) + 3355450; ++x)
            {
                builder.Append(x);
                builder.Append(',');
            }
            builder.Append("\"string_one\"");
            builder.Append(',');
            builder.Append("\"string_two\"");
            builder.Append(',');
            builder.Append("\"string_two\"");
            builder.Append(']');

            string json = builder.ToString();

            byte[]             binaryJson  = JsonTestUtils.ConvertTextToBinary(json);
            IJsonNavigator     navigator   = JsonNavigator.Create(binaryJson);
            int                count       = navigator.GetArrayItemCount(navigator.GetRootNode());
            IJsonNavigatorNode node        = navigator.GetArrayItemAt(navigator.GetRootNode(), count - 1);
            string             stringValue = navigator.GetStringValue(node);

            Assert.AreEqual("string_two", stringValue);
        }
        internal static JsonTokenInfo[] GetTokensFromObjectNode(IJsonNavigatorNode node, IJsonNavigator navigator, bool performCorrectnessCheck)
        {
            // Get the tokens through .GetObjectProperties
            List <JsonTokenInfo>         tokensFromGetProperties = new List <JsonTokenInfo>();
            IEnumerable <ObjectProperty> properties = navigator.GetObjectProperties(node);

            tokensFromGetProperties.Add(JsonTokenInfo.ObjectStart());
            foreach (ObjectProperty property in properties)
            {
                string fieldname = navigator.GetStringValue(property.NameNode);
                tokensFromGetProperties.Add(JsonTokenInfo.FieldName(fieldname));
                tokensFromGetProperties.AddRange(JsonNavigatorTests.GetTokensFromNode(property.ValueNode, navigator, performCorrectnessCheck));
            }
            tokensFromGetProperties.Add(JsonTokenInfo.ObjectEnd());

            if (performCorrectnessCheck)
            {
                // Get the tokens again through .TryGetObjectProperty
                List <JsonTokenInfo> tokensFromTryGetProperty = new List <JsonTokenInfo>();

                tokensFromTryGetProperty.Add(JsonTokenInfo.ObjectStart());
                foreach (ObjectProperty objectProperty in properties)
                {
                    ObjectProperty propertyFromTryGetProperty;
                    string         fieldname = navigator.GetStringValue(objectProperty.NameNode);
                    if (navigator.TryGetObjectProperty(node, fieldname, out propertyFromTryGetProperty))
                    {
                        tokensFromTryGetProperty.Add(JsonTokenInfo.FieldName(fieldname));
                        tokensFromTryGetProperty.AddRange(JsonNavigatorTests.GetTokensFromNode(propertyFromTryGetProperty.ValueNode, navigator, performCorrectnessCheck));
                    }
                    else
                    {
                        Assert.Fail($"Failed to get object property with name: {fieldname}");
                    }
                }
                tokensFromTryGetProperty.Add(JsonTokenInfo.ObjectEnd());
                Assert.AreEqual(properties.Count(), navigator.GetObjectPropertyCount(node));
                Assert.IsTrue(tokensFromGetProperties.SequenceEqual(tokensFromTryGetProperty));
            }

            return(tokensFromGetProperties.ToArray());
        }
Exemple #5
0
        /// <summary>
        /// Writes a json node to the internal buffer.
        /// </summary>
        /// <param name="jsonNavigator">The navigator to use to navigate the node</param>
        /// <param name="jsonNavigatorNode">The node to write.</param>
        public void WriteJsonNode(IJsonNavigator jsonNavigator, IJsonNavigatorNode jsonNavigatorNode)
        {
            if (jsonNavigator == null)
            {
                throw new ArgumentNullException($"{nameof(jsonNavigator)} can not be null");
            }

            if (jsonNavigatorNode == null)
            {
                throw new ArgumentNullException($"{nameof(jsonNavigatorNode)} can not be null");
            }

            // For now short circuit this to false until we figure out how to optimize this.
            bool sameFormat = jsonNavigator.SerializationFormat == this.SerializationFormat && (this.SerializationFormat == JsonSerializationFormat.Binary || this.SerializationFormat == JsonSerializationFormat.HybridRow);

            JsonNodeType jsonNodeType = jsonNavigator.GetNodeType(jsonNavigatorNode);

            // See if we can write the node without looking at it's value
            switch (jsonNodeType)
            {
            case JsonNodeType.Null:
                this.WriteNullValue();
                return;

            case JsonNodeType.False:
                this.WriteBoolValue(false);
                return;

            case JsonNodeType.True:
                this.WriteBoolValue(true);
                return;
            }

            // If the navigator has the same format as this writer then we try to retrieve the node raw JSON
            IReadOnlyList <byte> bufferedRawJson;

            if (sameFormat && jsonNavigator.TryGetBufferedRawJson(jsonNavigatorNode, out bufferedRawJson))
            {
                // Token type really doesn't make any difference other than whether this is a field name
                JsonTokenType jsonTokenType = (jsonNodeType == JsonNodeType.FieldName ? JsonTokenType.FieldName : JsonTokenType.Null);
                this.WriteRawJsonToken(jsonTokenType, bufferedRawJson);
            }
            else
            {
                // Either the formats did not match or we couldn't retrieve the buffered raw JSON
                switch (jsonNodeType)
                {
                case JsonNodeType.Number:
                    double numberValue = jsonNavigator.GetNumberValue(jsonNavigatorNode);
                    this.WriteNumberValue(numberValue);
                    break;

                case JsonNodeType.String:
                case JsonNodeType.FieldName:
                    bool fieldName = jsonNodeType == JsonNodeType.FieldName;
                    IReadOnlyList <byte> bufferedStringValue;
                    if (jsonNavigator.TryGetBufferedStringValue(jsonNavigatorNode, out bufferedStringValue))
                    {
                        if (fieldName)
                        {
                            this.WriteRawJsonToken(JsonTokenType.FieldName, bufferedStringValue);
                        }
                        else
                        {
                            this.WriteRawJsonToken(JsonTokenType.String, bufferedStringValue);
                        }
                    }
                    else
                    {
                        string value = jsonNavigator.GetStringValue(jsonNavigatorNode);
                        if (fieldName)
                        {
                            this.WriteFieldName(value);
                        }
                        else
                        {
                            this.WriteStringValue(value);
                        }
                    }

                    break;

                case JsonNodeType.Int8:
                {
                    sbyte number = jsonNavigator.GetInt8Value(jsonNavigatorNode);
                    this.WriteInt8Value(number);
                    break;
                }

                case JsonNodeType.Int16:
                {
                    short number = jsonNavigator.GetInt16Value(jsonNavigatorNode);
                    this.WriteInt16Value(number);
                    break;
                }

                case JsonNodeType.Int32:
                {
                    int number = jsonNavigator.GetInt32Value(jsonNavigatorNode);
                    this.WriteInt32Value(number);
                    break;
                }

                case JsonNodeType.Int64:
                {
                    long number = jsonNavigator.GetInt64Value(jsonNavigatorNode);
                    this.WriteInt64Value(number);
                    break;
                }

                case JsonNodeType.UInt32:
                {
                    uint number = jsonNavigator.GetUInt32Value(jsonNavigatorNode);
                    this.WriteUInt32Value(number);
                    break;
                }

                case JsonNodeType.Float32:
                {
                    float number = jsonNavigator.GetFloat32Value(jsonNavigatorNode);
                    this.WriteFloat32Value(number);
                    break;
                }

                case JsonNodeType.Float64:
                {
                    double number = jsonNavigator.GetFloat64Value(jsonNavigatorNode);
                    this.WriteFloat64Value(number);
                    break;
                }

                case JsonNodeType.Guid:
                {
                    Guid number = jsonNavigator.GetGuidValue(jsonNavigatorNode);
                    this.WriteGuidValue(number);
                    break;
                }

                case JsonNodeType.Binary:
                {
                    IReadOnlyList <byte> bufferedBinaryValue;
                    if (jsonNavigator.TryGetBufferedBinaryValue(jsonNavigatorNode, out bufferedBinaryValue))
                    {
                        this.WriteRawJsonToken(JsonTokenType.Binary, bufferedBinaryValue);
                    }
                    else
                    {
                        IReadOnlyList <byte> value = jsonNavigator.GetBinaryValue(jsonNavigatorNode);
                        this.WriteBinaryValue(value);
                    }

                    break;
                }

                case JsonNodeType.Array:
                    this.WriteArrayStart();
                    foreach (IJsonNavigatorNode arrayItem in jsonNavigator.GetArrayItems(jsonNavigatorNode))
                    {
                        this.WriteJsonNode(jsonNavigator, arrayItem);
                    }

                    this.WriteArrayEnd();
                    break;

                case JsonNodeType.Object:
                    this.WriteObjectStart();
                    foreach (ObjectProperty objectProperty in jsonNavigator.GetObjectProperties(jsonNavigatorNode))
                    {
                        this.WriteJsonNode(jsonNavigator, objectProperty.NameNode);
                        this.WriteJsonNode(jsonNavigator, objectProperty.ValueNode);
                    }

                    this.WriteObjectEnd();
                    break;

                default:
                    throw new ArgumentException($"Unexpected JsonNodeType: {jsonNodeType}");
                }
            }
        }
        /// <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;

            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(new ArraySegment <byte>(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);
        }