Question

I have indexed an object defined as such:

public class CourseOffering
{
    public int CourseId { get; set; }
    public string Title { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public ICollection<TimeBlock> TimeBlocks { get; set; }
}

The TimeBlock class is defined as:

public class TimeBlock
{
    public DayOfWeek Day { get; set; }
    public LocalTime StartTime { get; set; }
    public LocalTime EndTime { get; set; }
}

When calling the dynamic search method, everything works fine (presumably because it doesn't know what to deserialize to). The results are returned correctly.

When calling the generic search method and passing in the CourseOffering type, the default serializer has problems deserializing the LocalTime objects. I get the following JsonReaderException:

Error reading integer. Unexpected token: StartObject. Path 'hits.hits[0]._source.timeBlocks[0].startTime', line 1, position 655.

I have tried adding the LocalTimeConverter like so:

var settings = new ConnectionSettings(uri);
settings.SetDefaultIndex(index);
settings.AddContractJsonConverters(t => typeof (LocalTime).IsAssignableFrom(t) ? NodaConverters.LocalTimeConverter : null);

But it results in this JsonReaderException:

Could not convert string to integer: 12:30:00. Path 'hits.hits[0]._source.timeBlocks[0].startTime', line 1, position 664.

I honestly can't tell if I'm doing something wrong or if there is an issue somewhere. Any assistance would be greatly appreciated.

Was it helpful?

Solution

I learned a new lesson today: Always post your code on Stack Overflow exactly as it appears in your problem. In an attempt to simplify the problem that I was having, I left out one very glaring issue with serializing/deserializing objects: I did not have a public parameterless constructor on my TimeBlock class.

For clarity, this was my actual TimeBlock class:

public class TimeBlock
{
    public DayOfWeek Day { get; set; }
    public LocalTime StartTime { get; set; }
    public LocalTime EndTime { get; set; }

    public TimeBlock(int day, int startTime, int endTime)
    {
        Day = (DayOfWeek)day;
        StartTime = new LocalTime(startTime / 100, startTime % 100);
        EndTime = new LocalTime(endTime / 100, endTime % 100);
    }

    public string GetDayOfWeekString()
    {
        return CultureInfo.CurrentCulture.DateTimeFormat.GetDayName(Day);
    }
}

Adding in the local constructor makes everything peachy.

public TimeBlock() {}

OTHER TIPS

Using NEST 5.5.0 / Nodatime 2.2.2, I encountered a similar error but had to use the following to enable Nodatime's JSON converters:

var pool = new SingleNodeConnectionPool( new Uri( "http://localhost:9200" ) );
var settings = new ConnectionSettings( pool, new HttpConnection(), new SerializerFactory( ( s, v ) => s.ConfigureForNodaTime( DateTimeZoneProviders.Tzdb ) ) );

Modern answer for NEST 7.13.2 and NodaTime 3.0.5

Additional NuGet packages required:

  • NEST.JsonNetSerializer
  • NodaTime.Serialization.JsonNet

Implementation:

var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

var settings = new ConnectionSettings(
    pool,
    sourceSerializer: (s, v) =>
        new JsonNetSerializer(s, v,
            () => new JsonSerializerSettings()
                .ConfigureForNodaTime(DateTimeZoneProviders.Tzdb)
        )
    );

return new ElasticClient(settings);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top