diff --git a/src/Nest/CommonOptions/Sorting/SortFormatter.cs b/src/Nest/CommonOptions/Sorting/SortFormatter.cs index 1df943736d5..f6482bca667 100644 --- a/src/Nest/CommonOptions/Sorting/SortFormatter.cs +++ b/src/Nest/CommonOptions/Sorting/SortFormatter.cs @@ -22,55 +22,82 @@ public ISort Deserialize(ref JsonReader reader, IJsonFormatterResolver formatter { ISort sort = null; - var count = 0; - while (reader.ReadIsInObject(ref count)) + switch (reader.GetCurrentJsonToken()) { - var sortProperty = reader.ReadPropertyNameSegmentRaw(); - if (SortFields.TryGetValue(sortProperty, out var value)) + case JsonToken.String: { - switch (value) + var sortProperty = reader.ReadString(); + sort = new FieldSort { Field = sortProperty }; + break; + } + case JsonToken.BeginObject: + { + var count = 0; + while (reader.ReadIsInObject(ref count)) { - case 0: - var propCount = 0; - string field = null; - var geoDistanceSegment = reader.ReadNextBlockSegment(); - var geoDistanceReader = new JsonReader(geoDistanceSegment.Array, geoDistanceSegment.Offset); - IEnumerable points = null; - while (geoDistanceReader.ReadIsInObject(ref propCount)) + var sortProperty = reader.ReadPropertyNameSegmentRaw(); + if (SortFields.TryGetValue(sortProperty, out var value)) + { + switch (value) { - var nameSegment = geoDistanceReader.ReadPropertyNameSegmentRaw(); - if (geoDistanceReader.GetCurrentJsonToken() == JsonToken.BeginArray) - { - field = nameSegment.Utf8String(); - points = formatterResolver.GetFormatter>() + case 0: + var propCount = 0; + string field = null; + var geoDistanceSegment = reader.ReadNextBlockSegment(); + var geoDistanceReader = new JsonReader(geoDistanceSegment.Array, geoDistanceSegment.Offset); + IEnumerable points = null; + while (geoDistanceReader.ReadIsInObject(ref propCount)) + { + var nameSegment = geoDistanceReader.ReadPropertyNameSegmentRaw(); + if (geoDistanceReader.GetCurrentJsonToken() == JsonToken.BeginArray) + { + field = nameSegment.Utf8String(); + points = formatterResolver.GetFormatter>() + .Deserialize(ref geoDistanceReader, formatterResolver); + break; + } + + // skip value if not array + geoDistanceReader.ReadNextBlock(); + } + geoDistanceReader = new JsonReader(geoDistanceSegment.Array, geoDistanceSegment.Offset); + var geoDistanceSort = formatterResolver.GetFormatter() .Deserialize(ref geoDistanceReader, formatterResolver); + geoDistanceSort.Field = field; + geoDistanceSort.Points = points; + sort = geoDistanceSort; break; - } - - // skip value if not array - geoDistanceReader.ReadNextBlock(); + case 1: + sort = formatterResolver.GetFormatter() + .Deserialize(ref reader, formatterResolver); + break; + } + } + else + { + var field = sortProperty.Utf8String(); + FieldSort sortField; + if (reader.GetCurrentJsonToken() == JsonToken.String) + { + var sortOrder = formatterResolver.GetFormatter() + .Deserialize(ref reader, formatterResolver); + sortField = new FieldSort { Field = field, Order = sortOrder }; } - geoDistanceReader = new JsonReader(geoDistanceSegment.Array, geoDistanceSegment.Offset); - var geoDistanceSort = formatterResolver.GetFormatter() - .Deserialize(ref geoDistanceReader, formatterResolver); - geoDistanceSort.Field = field; - geoDistanceSort.Points = points; - sort = geoDistanceSort; - break; - case 1: - sort = formatterResolver.GetFormatter() - .Deserialize(ref reader, formatterResolver); - break; + else + { + sortField = formatterResolver.GetFormatter() + .Deserialize(ref reader, formatterResolver); + sortField.Field = field; + } + + sort = sortField; + } } + + break; } - else - { - var field = sortProperty.Utf8String(); - var sortField = formatterResolver.GetFormatter() - .Deserialize(ref reader, formatterResolver); - sortField.Field = field; - sort = sortField; - } + default: + throw new JsonParsingException($"Cannot deserialize {nameof(ISort)} from {reader.GetCurrentJsonToken()}"); } return sort; diff --git a/tests/Tests.Reproduce/GitHubIssue4797.cs b/tests/Tests.Reproduce/GitHubIssue4797.cs new file mode 100644 index 00000000000..be6da4dc387 --- /dev/null +++ b/tests/Tests.Reproduce/GitHubIssue4797.cs @@ -0,0 +1,46 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Text; +using Elastic.Elasticsearch.Xunit.XunitPlumbing; +using FluentAssertions; +using Nest; +using Tests.Core.Client; + +namespace Tests.Reproduce +{ + public class GitHubIssue4797 + { + [U] + public void DeserializeSortWithOnlyFieldAndOrder() + { + var json = @" + { + ""sort"" : [ + { ""post_date"" : {""order"" : ""asc""}}, + ""user"", + { ""name"" : ""desc"" }, + { ""age"" : ""desc"" }, + ""_score"" + ], + ""query"" : { + ""term"" : { ""user"" : ""kimchy"" } + } + } + "; + + var bytes = Encoding.UTF8.GetBytes(json); + var client = TestClient.FixedInMemoryClient(bytes); + + using var stream = client.ConnectionSettings.MemoryStreamFactory.Create(bytes); + var request = client.RequestResponseSerializer.Deserialize(stream); + + request.Should().NotBeNull(); + request.Sort.Should().NotBeNull().And.HaveCount(5); + request.Sort[1].SortKey.Should().Be("user"); + request.Sort[2].SortKey.Should().Be("name"); + request.Sort[2].Order.Should().Be(SortOrder.Descending); + } + } +}