Skip to content

Commit 109bcb0

Browse files
authored
Use serializer when deserializing LazyDocument to T (#2791)
* Use serializer when deserializing LazyDocument to T When converting a LazyDocument to type T, use the JsonNetSerializer configured, along with all registered contract resolvers. Fixes #2788 * Direct cast * Add non-generic overload for As() Relates #2408
1 parent 9b0d36b commit 109bcb0

File tree

4 files changed

+130
-16
lines changed

4 files changed

+130
-16
lines changed
Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Newtonsoft.Json;
1+
using System;
2+
using Newtonsoft.Json;
23
using Newtonsoft.Json.Linq;
34

45
namespace Nest
@@ -7,21 +8,37 @@ namespace Nest
78
public interface ILazyDocument
89
{
910
/// <summary>
10-
///
11+
/// Creates an instance of <typeparamref name="T"/> from this
12+
/// <see cref="ILazyDocument"/> instance
1113
/// </summary>
12-
/// <typeparam name="T"></typeparam>
13-
/// <returns></returns>
14+
/// <typeparam name="T">The type</typeparam>
1415
T As<T>() where T : class;
16+
17+
/// <summary>
18+
/// Creates an instance of <paramref name="objectType"/> from this
19+
/// <see cref="ILazyDocument"/> instance
20+
/// </summary>
21+
/// <typeparam name="T">The type</typeparam>
22+
object As(Type objectType);
1523
}
1624

1725
public class LazyDocument : ILazyDocument
1826
{
1927
internal JToken _Value { get; set; }
28+
internal JsonSerializer _Serializer { get; set; }
2029

30+
/// <inheritdoc />
2131
public T As<T>() where T : class
2232
{
2333
var jToken = this._Value;
24-
return jToken?.ToObject<T>();
34+
return jToken?.ToObject<T>(_Serializer);
35+
}
36+
37+
/// <inheritdoc />
38+
public object As(Type objectType)
39+
{
40+
var jToken = this._Value;
41+
return jToken?.ToObject(objectType, _Serializer);
2542
}
2643
}
2744
}

src/Nest/CommonAbstractions/LazyDocument/LazyDocumentJsonConverter.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,26 @@ internal class LazyDocumentJsonConverter : JsonConverter
88
{
99
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
1010
{
11-
var d = value as LazyDocument;
11+
var d = (LazyDocument)value;
1212
if (d?._Value == null)
13+
{
14+
writer.WriteNull();
1315
return;
16+
}
17+
1418
writer.WriteToken(d._Value.CreateReader());
1519
}
1620

1721
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
1822
{
1923
var document = serializer.Deserialize(reader) as JToken;
20-
return new LazyDocument { _Value = document };
24+
return new LazyDocument
25+
{
26+
_Value = document,
27+
_Serializer = serializer
28+
};
2129
}
2230

23-
public override bool CanConvert(Type objectType)
24-
{
25-
return true;
26-
}
31+
public override bool CanConvert(Type objectType) => true;
2732
}
2833
}

src/Nest/Search/Search/Hits/InnerHitsResult.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@ namespace Nest
66
{
77
public class InnerHitsResult
88
{
9-
109
[JsonProperty("hits")]
1110
public InnerHitsMetaData Hits { get; internal set; }
1211

13-
public IEnumerable<T> Documents<T>() where T : class
14-
{
15-
return this.Hits == null ? Enumerable.Empty<T>() : this.Hits.Documents<T>();
16-
}
12+
/// <summary>
13+
/// Retrieve <see cref="Hits"/> documents as a strongly typed
14+
/// collection
15+
/// </summary>
16+
/// <typeparam name="T">The hits document type</typeparam>
17+
public IEnumerable<T> Documents<T>() where T : class =>
18+
this.Hits == null ? Enumerable.Empty<T>() : this.Hits.Documents<T>();
1719
}
1820
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System;
2+
using System.Linq;
3+
using Elasticsearch.Net;
4+
using FluentAssertions;
5+
using FluentAssertions.Common;
6+
using Nest;
7+
using Tests.Framework;
8+
using Tests.Framework.ManagedElasticsearch.Clusters;
9+
using Xunit;
10+
11+
namespace Tests.Reproduce
12+
{
13+
public class GithubIssue2788 : IClusterFixture<WritableCluster>
14+
{
15+
private readonly WritableCluster _cluster;
16+
17+
public GithubIssue2788(WritableCluster cluster)
18+
{
19+
_cluster = cluster;
20+
}
21+
22+
// sample mapping with nested objects with TimeSpan field
23+
class Root
24+
{
25+
[Nested]
26+
public Child[] Children { get; set; }
27+
}
28+
29+
class Child
30+
{
31+
public TimeSpan StartTime { get; set; }
32+
33+
public TimeSpan EndTime { get; set; }
34+
}
35+
36+
[I]
37+
public void CanDeserializeNumberToTimeSpanInInnerHits()
38+
{
39+
var indexName = "sample";
40+
var client = _cluster.Client;
41+
42+
//create index with automapping
43+
client.CreateIndex(indexName, create => create
44+
.Mappings(mappings => mappings
45+
.Map<Root>(map => map
46+
.AutoMap()
47+
)
48+
)
49+
);
50+
51+
var startTime = new TimeSpan(1, 2, 3);
52+
var endTime = new TimeSpan(2, 3, 4);
53+
54+
client.Index(new Root
55+
{
56+
Children = new[]
57+
{
58+
new Child
59+
{
60+
StartTime = startTime,
61+
EndTime = endTime
62+
63+
}
64+
}
65+
}, index => index
66+
.Index(indexName)
67+
.Refresh(Refresh.WaitFor)
68+
);
69+
70+
var result = client.Search<Root>(search => search
71+
.Query(query => query
72+
.Nested(nested => nested
73+
.Query(nestedQuery => nestedQuery
74+
.MatchAll()
75+
)
76+
.Path(i => i.Children)
77+
.InnerHits()
78+
)
79+
)
80+
.Index(indexName)
81+
);
82+
83+
var child = result.Hits.First().InnerHits.Single().Value.Documents<Child>().Single();
84+
85+
child.Should().NotBeNull();
86+
child.StartTime.Should().Be(startTime);
87+
child.EndTime.Should().Be(endTime);
88+
}
89+
}
90+
}

0 commit comments

Comments
 (0)