/// <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(); } } }