Skip to content

Commit

Permalink
Use serializer when deserializing LazyDocument to T (#2791)
Browse files Browse the repository at this point in the history
* 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

(cherry picked from commit 109bcb0)
  • Loading branch information
russcam committed Jun 29, 2017
1 parent 45ac1fe commit bd71ff8
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 16 deletions.
27 changes: 22 additions & 5 deletions src/Nest/CommonAbstractions/LazyDocument/LazyDocument.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Nest
Expand All @@ -7,21 +8,37 @@ namespace Nest
public interface ILazyDocument
{
/// <summary>
///
/// Creates an instance of <typeparamref name="T"/> from this
/// <see cref="ILazyDocument"/> instance
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
/// <typeparam name="T">The type</typeparam>
T As<T>() where T : class;

/// <summary>
/// Creates an instance of <paramref name="objectType"/> from this
/// <see cref="ILazyDocument"/> instance
/// </summary>
/// <typeparam name="T">The type</typeparam>
object As(Type objectType);
}

public class LazyDocument : ILazyDocument
{
internal JToken _Value { get; set; }
internal JsonSerializer _Serializer { get; set; }

/// <inheritdoc />
public T As<T>() where T : class
{
var jToken = this._Value;
return jToken?.ToObject<T>();
return jToken?.ToObject<T>(_Serializer);
}

/// <inheritdoc />
public object As(Type objectType)
{
var jToken = this._Value;
return jToken?.ToObject(objectType, _Serializer);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,26 @@ internal class LazyDocumentJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var d = value as LazyDocument;
var d = (LazyDocument)value;
if (d?._Value == null)
{
writer.WriteNull();
return;
}

writer.WriteToken(d._Value.CreateReader());
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var document = serializer.Deserialize(reader) as JToken;
return new LazyDocument { _Value = document };
return new LazyDocument
{
_Value = document,
_Serializer = serializer
};
}

public override bool CanConvert(Type objectType)
{
return true;
}
public override bool CanConvert(Type objectType) => true;
}
}
12 changes: 7 additions & 5 deletions src/Nest/Search/Search/Hits/InnerHitsResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ namespace Nest
{
public class InnerHitsResult
{

[JsonProperty("hits")]
public InnerHitsMetaData Hits { get; internal set; }

public IEnumerable<T> Documents<T>() where T : class
{
return this.Hits == null ? Enumerable.Empty<T>() : this.Hits.Documents<T>();
}
/// <summary>
/// Retrieve <see cref="Hits"/> documents as a strongly typed
/// collection
/// </summary>
/// <typeparam name="T">The hits document type</typeparam>
public IEnumerable<T> Documents<T>() where T : class =>
this.Hits == null ? Enumerable.Empty<T>() : this.Hits.Documents<T>();
}
}
90 changes: 90 additions & 0 deletions src/Tests/Reproduce/GithubIssue2788.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.Linq;
using Elasticsearch.Net;
using FluentAssertions;
using FluentAssertions.Common;
using Nest;
using Tests.Framework;
using Tests.Framework.ManagedElasticsearch.Clusters;
using Xunit;

namespace Tests.Reproduce
{
public class GithubIssue2788 : IClusterFixture<WritableCluster>
{
private readonly WritableCluster _cluster;

public GithubIssue2788(WritableCluster cluster)
{
_cluster = cluster;
}

// sample mapping with nested objects with TimeSpan field
class Root
{
[Nested]
public Child[] Children { get; set; }
}

class Child
{
public TimeSpan StartTime { get; set; }

public TimeSpan EndTime { get; set; }
}

[I]
public void CanDeserializeNumberToTimeSpanInInnerHits()
{
var indexName = "sample";
var client = _cluster.Client;

//create index with automapping
client.CreateIndex(indexName, create => create
.Mappings(mappings => mappings
.Map<Root>(map => map
.AutoMap()
)
)
);

var startTime = new TimeSpan(1, 2, 3);
var endTime = new TimeSpan(2, 3, 4);

client.Index(new Root
{
Children = new[]
{
new Child
{
StartTime = startTime,
EndTime = endTime

}
}
}, index => index
.Index(indexName)
.Refresh(Refresh.WaitFor)
);

var result = client.Search<Root>(search => search
.Query(query => query
.Nested(nested => nested
.Query(nestedQuery => nestedQuery
.MatchAll()
)
.Path(i => i.Children)
.InnerHits()
)
)
.Index(indexName)
);

var child = result.Hits.First().InnerHits.Single().Value.Documents<Child>().Single();

child.Should().NotBeNull();
child.StartTime.Should().Be(startTime);
child.EndTime.Should().Be(endTime);
}
}
}

0 comments on commit bd71ff8

Please sign in to comment.