Skip to content

Use serializer when deserializing LazyDocument to T #2791

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 29, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
}
}