Beispiel #1
0
        /// <summary>
        /// Parse a SearchSuggestion and its model.
        /// </summary>
        /// <param name="reader">The JSON reader.</param>
        /// <param name="typeToConvert">The type to parse into.</param>
        /// <param name="options">Serialization options.</param>
        /// <returns>The deserialized suggestion.</returns>
        public override SearchSuggestion <T> Read(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options)
        {
            Debug.Assert(options != null);
            SearchSuggestion <T> suggestion = new SearchSuggestion <T>();

            // Clone the reader so we can get the search text property without
            // advancing the reader over any properties needed to deserialize
            // the user's model type.
            Utf8JsonReader clone = reader;

            clone.Expects(JsonTokenType.StartObject);
            while (clone.Read() && clone.TokenType != JsonTokenType.EndObject)
            {
                string name = clone.ExpectsPropertyName();
                if (name == Constants.SearchTextKey)
                {
                    suggestion.Text = clone.ExpectsString();
                    break;
                }
            }

            // Deserialize the model
            T document = JsonSerializer.Deserialize <T>(ref reader, options);

            suggestion.Document = document;

            return(suggestion);
        }
Beispiel #2
0
        /// <summary>
        /// Read the @search.facets property value.
        /// </summary>
        /// <param name="reader">The JSON reader.</param>
        /// <param name="results">The SearchResults to add the facets to.</param>
        /// <param name="options">JSON serializer options.</param>
        private static void ReadFacets(
            ref Utf8JsonReader reader,
            SearchResults <T> results,
            JsonSerializerOptions options)
        {
            Debug.Assert(results != null);

            // Facets are optional, so short circuit if nothing is found
            if (reader.TokenType == JsonTokenType.Null)
            {
                return;
            }

            results.Facets = new Dictionary <string, IList <FacetResult> >();
            reader.Expects(JsonTokenType.StartObject);
            while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
            {
                // Get the name of the facet
                string facetName = reader.ExpectsPropertyName();

                // Get the values of the facet
                List <FacetResult> facets = new List <FacetResult>();
                reader.Expects(JsonTokenType.StartArray);
                while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
                {
                    FacetResult facet = ReadFacetResult(ref reader, options);
                    facets.Add(facet);
                }

                // Add the facet to the results
                results.Facets[facetName] = facets;
            }
        }
Beispiel #3
0
        /// <summary>
        /// Parse the SearchResults and its search results.
        /// </summary>
        /// <param name="reader">The JSON reader.</param>
        /// <param name="typeToConvert">The type to parse into.</param>
        /// <param name="options">Serialization options.</param>
        /// <returns>The deserialized search results.</returns>
        public override SearchResults <T> Read(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options)
        {
            Debug.Assert(typeToConvert != null);
            Debug.Assert(typeToConvert.IsAssignableFrom(typeof(SearchResults <T>)));
            Debug.Assert(options != null);

            SearchResults <T> results = new SearchResults <T>();

            reader.Expects(JsonTokenType.StartObject);
            while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
            {
                switch (reader.ExpectsPropertyName())
                {
                case Constants.ODataCountKey:
                    results.TotalCount = reader.ExpectsNullableLong();
                    break;

                case Constants.SearchCoverageKey:
                    results.Coverage = reader.ExpectsNullableDouble();
                    break;

                case Constants.SearchFacetsKey:
                    ReadFacets(ref reader, results, options);
                    break;

                case Constants.ODataNextLinkKey:
                    results.NextUri = new Uri(reader.ExpectsString());
                    break;

                case Constants.SearchNextPageKey:
                    results.NextOptions = ReadNextPageOptions(ref reader);
                    break;

                case Constants.ValueKey:
                    reader.Expects(JsonTokenType.StartArray);
                    while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
                    {
                        SearchResult <T> result = _resultConverter.Read(ref reader, _resultType, options);
                        results.Values.Add(result);
                    }
                    break;

                default:
                    // Ignore other properties (including OData context, etc.)
                    reader.Skip();
                    break;
                }
            }
            return(results);
        }
Beispiel #4
0
        /// <summary>
        /// Parse a SearchResult and its model.
        /// </summary>
        /// <param name="reader">The JSON reader.</param>
        /// <param name="typeToConvert">The type to parse into.</param>
        /// <param name="options">Serialization options.</param>
        /// <returns>The deserialized search result.</returns>
        public override SearchResult <T> Read(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options)
        {
            Debug.Assert(options != null);
            SearchResult <T> result = new SearchResult <T>();

            // Clone the reader so we can get the search text property without
            // advancing the reader over any properties needed to deserialize
            // the user's model type.
            Utf8JsonReader clone = reader;

            // Keep track of the properties we've found so we can stop reading
            // through the cloned object
            bool parsedScore      = false;
            bool parsedHighlights = false;

            clone.Expects(JsonTokenType.StartObject);
            while (
                (!parsedScore || !parsedHighlights) &&
                clone.Read() &&
                clone.TokenType != JsonTokenType.EndObject)
            {
                string name = clone.ExpectsPropertyName();
                if (name == Constants.SearchScoreKey)
                {
                    parsedScore  = true;
                    result.Score = clone.ExpectsNullableDouble();
                }
                else if (name == Constants.SearchHighlightsKey)
                {
                    parsedHighlights = true;
                    ReadHighlights(ref clone, result);
                }
                else
                {
                    // Skip the rest of the next property's value
                    clone.Skip();
                }
            }

            // Deserialize the model
            T document = JsonSerializer.Deserialize <T>(ref reader, options);

            result.Document = document;

            return(result);
        }
Beispiel #5
0
        /// <summary>
        /// Read the @search.highlights property value.
        /// </summary>
        /// <param name="reader">The JSON reader.</param>
        /// <param name="result">The SearchResult to add the highlights to.</param>
        private static void ReadHighlights(ref Utf8JsonReader reader, SearchResult <T> result)
        {
            Debug.Assert(result != null);
            result.Highlights = new Dictionary <string, IList <string> >();
            reader.Expects(JsonTokenType.StartObject);
            while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
            {
                // Get the highlight field name
                string name = reader.ExpectsPropertyName();

                // Get the highlight values
                List <string> values = new List <string>();
                reader.Expects(JsonTokenType.StartArray);
                while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
                {
                    values.Add(reader.ExpectsString());
                }

                // Add the highlight
                result.Highlights[name] = values;
            }
        }
Beispiel #6
0
        /// <summary>
        /// Parse the SuggestResults and its suggestions.
        /// </summary>
        /// <param name="reader">The JSON reader.</param>
        /// <param name="typeToConvert">The type to parse into.</param>
        /// <param name="options">Serialization options.</param>
        /// <returns>The deserialized suggestions.</returns>
        public override SuggestResults <T> Read(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options)
        {
            Debug.Assert(typeToConvert != null);
            Debug.Assert(typeToConvert.IsAssignableFrom(typeof(SuggestResults <T>)));
            Debug.Assert(options != null);

            SuggestResults <T> suggestions = new SuggestResults <T>();

            reader.Expects(JsonTokenType.StartObject);
            while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
            {
                switch (reader.ExpectsPropertyName())
                {
                case Constants.SearchCoverageKey:
                    suggestions.Coverage = reader.ExpectsNullableDouble();
                    break;

                case Constants.ValueKey:
                    reader.Expects(JsonTokenType.StartArray);
                    while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
                    {
                        SearchSuggestion <T> suggestion =
                            _suggestionConverter.Read(ref reader, _suggestionType, options);
                        suggestions.Results.Add(suggestion);
                    }
                    break;

                default:
                    // Ignore other properties (including OData context, etc.)
                    reader.Skip();
                    break;
                }
            }
            return(suggestions);
        }
Beispiel #7
0
        /// <summary>
        /// Read the facet result value.
        /// </summary>
        /// <param name="reader">JSON reader.</param>
        /// <param name="options">Serializer options.</param>
        /// <returns>The facet result.</returns>
        private static FacetResult ReadFacetResult(
            ref Utf8JsonReader reader,
            JsonSerializerOptions options)
        {
            FacetResult facet = new FacetResult();

            reader.Expects(JsonTokenType.StartObject);
            while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
            {
                // Get the name of the facet property
                string facetName = reader.ExpectsPropertyName();
                if (facetName == Constants.CountKey)
                {
                    facet.Count = reader.ExpectsNullableLong();
                }
                else
                {
                    object value = reader.ReadObject(options);
                    facet[facetName] = value;
                }
            }
            return(facet);
        }
Beispiel #8
0
        /// <summary>
        /// Parse JSON into a SearchDocument.
        /// </summary>
        /// <param name="reader">The JSON reader.</param>
        /// <param name="typeToConvert">The type to convert to.</param>
        /// <param name="options">Serialization options.</param>
        /// <param name="recursionDepth">
        /// Depth of the current read recursion to bail out of circular
        /// references.
        /// </param>
        /// <returns>A deserialized SearchDocument.</returns>
        public static SearchDocument ReadSearchDocument(
            ref Utf8JsonReader reader,
            Type typeToConvert,
            JsonSerializerOptions options,
            int?recursionDepth = null)
        {
            Debug.Assert(typeToConvert != null);

            Debug.Assert(typeToConvert.IsAssignableFrom(typeof(SearchDocument)));

            recursionDepth ??= options.GetMaxRecursionDepth();
            AssertRecursionDepth(recursionDepth.Value);

            SearchDocument doc = new SearchDocument();

            reader.Expects(JsonTokenType.StartObject);
            while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
            {
                string propertyName = reader.ExpectsPropertyName();

                // Ignore OData properties - we don't expose those on custom
                // user schemas
                if (!propertyName.StartsWith(Constants.ODataKeyPrefix, StringComparison.OrdinalIgnoreCase))
                {
                    object value = ReadSearchDocObject(ref reader, recursionDepth.Value - 1);
                    doc[propertyName] = value;
                }
                else
                {
                    reader.Skip();
                }
            }
            return(doc);

            // TODO: #10596 - Investigate using JsonSerializer for reading SearchDocument properties

            // The built in converters for JsonSerializer are a little more
            // helpful than we want right now and will do things like turn "1"
            // to the integer 1 instead of a string.  The number of special
            // cases needed for converting dynamic documents is small enough
            // that we're hard coding them here for now.  We'll revisit with
            // Search experts and their customer scenarios to get this right in
            // the next preview.
            object ReadSearchDocObject(ref Utf8JsonReader reader, int depth)
            {
                AssertRecursionDepth(depth);
                switch (reader.TokenType)
                {
                case JsonTokenType.String:
                case JsonTokenType.Number:
                case JsonTokenType.True:
                case JsonTokenType.False:
                case JsonTokenType.None:
                case JsonTokenType.Null:
                    return(ReadPrimitiveValue(ref reader));

                case JsonTokenType.StartObject:
                    // TODO: #10592- Unify on an Azure.Core spatial type

                    // Return a complex object
                    return(ReadSearchDocument(ref reader, typeof(SearchDocument), options, depth - 1));

                case JsonTokenType.StartArray:
                    var list = new List <object>();
                    while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
                    {
                        recursionDepth--;
                        object value = ReadSearchDocObject(ref reader, depth - 1);
                        list.Add(value);
                    }
                    return(list.ToArray());

                default:
                    throw new JsonException();
                }
            }
        }