bchavez / RethinkDb.Driver

:headphones: A NoSQL C#/.NET RethinkDB database driver with 100% ReQL API coverage.
http://rethinkdb.com/api/java
Other
384 stars 134 forks source link

DateTime field in JObject Deserialization #99

Closed alana1 closed 8 years ago

alana1 commented 8 years ago

Hello,

I have a changefeed and returns JObject. In the JObject contains the DateTime field. However, the JObject returns the epoch time. When deserializing JObject to strongly type object, any properties with DateTime epoch time is not converted to the original datetime utc format we are expecting. How can I deserialize the jobject and return correct datetime. A sample of the json is below.

{
  "ChatQueueId": 1,
  "ChatRequestNo": 0,
  "DeliveredTime": {
    "$reql_type$": "TIME",
    "epoch_time": -62135596800,
    "timezone": "+00:00"
  },
  "EmailAddress": "mham@ctintegrations.com",
  "EndTime": {
    "$reql_type$": "TIME",
    "epoch_time": 1472074019.588,
    "timezone": "+00:00"
  },
  "EstablishedTime": {
    "$reql_type$": "TIME",
    "epoch_time": -62135596800,
    "timezone": "+00:00"
  },
  "FirstName": "Jerry",
  "InitialMessage": null,
  "KeyValues": [
    {
      "Key": "defid",
      "Value": "5454564"
    },
    {
      "Key": "defid",
      "Value": "5454564"
    },
    {
      "Key": "defid",
      "Value": "5454564"
    }
  ],
  "LastName": "McGiver",
  "RequestTime": {
    "$reql_type$": "TIME",
    "epoch_time": 1472070419.588,
    "timezone": "+00:00"
  },
  "SiteId": 0,
  "id": "70f6d8a0-4375-41f1-9db9-129683b7f3a1"
}
bchavez commented 8 years ago

Just a few questions:

Also, are you customizing the Newtonsoft.Json serializer? If so, can you post your configuration? Thanks.

alana1 commented 8 years ago

Hello,

I am using C# driver version 2.3.9.0. RethinkDB for Windows version 2.3.4. I am not using customized serializer.

bchavez commented 8 years ago
bchavez commented 8 years ago

Hey @alana1 ,

This must be due to something else... (like customizing the serializer) the following unit test passes in the C# driver currently:

[Test]
public void try_basic_datetime_deseralization()
{
    var obj = new JObject
        {
            ["Name"] = "Brian",
            ["dob"] = DateTime.Parse("8/24/2016")
        };

    var fromDb = R.Expr(obj).RunResult<JObject>(conn);
    var dateTimeValue = fromDb["dob"] as JValue;
    dateTimeValue.Type.Should().Be(JTokenType.Date);
    dateTimeValue.Value.Should().BeOfType<DateTime>();
}

Protocol Trace

TRACE JSON Send: Token: 3, JSON: [1,{"Name":"Brian","dob":{"$reql_type$":"TIME","epoch_time":1472022000.0,"timezone":"-07:00"}},{}]
TRACE JSON Recv: Token: 3, JSON: {"t":1,"r":[{"Name":"Brian","dob":{"$reql_type$":"TIME","epoch_time":1472022000,"timezone":"-07:00"}}]}

So we are converting the time pseudo types correctly with JObject. You'll have to send me a PR with a failing unit test in order to debug this more. :confused:

:hourglass_flowingsand: :mag: [**"But I still haven't found what I'm for..."**_](https://www.youtube.com/watch?v=wdCJRybAtso)

bchavez commented 8 years ago

@alana1 by any chance, are you using .Run<List<JObject>>() or something like it? If so, this would be a gotcha.

https://github.com/bchavez/RethinkDb.Driver/wiki/GOTCHA!#reql_type-all-up-in-my-jobject


:busstop: :bus: _"Fe, Fi, Fo, Fum... Well, I'll be darn here it comes... The Double Dutch Bus is on the street"_

alana1 commented 8 years ago

I am using RunChanges(conn). Is that okay?

bchavez commented 8 years ago

Ahhhh. Okay, that makes sense now. Yeah, that would be a bug in the driver.

.RunChanges is a wrapper for .RunCursor<Change<JObject>> which is just like the gotcha above; except this on is on meeee!!!! :bug:

Haha, okay, I'll work on getting a fix for you soon.

:watch: :citysunset: [**"I just can't wait... I just can't wait... for saturday night..."**_](https://www.youtube.com/watch?v=wOjGmpmvGz8#t=2m)

alana1 commented 8 years ago

Thank you and much appreciated.

bchavez commented 8 years ago

Hey @alana1 , as a temporary workaround, instead of using .RunChanges<JObject>(conn), could you use .RunCursor<JObject>(conn) instead? It's pretty much the same thing, and it will resolve your issue temporarily.

I'm going to need a little more time to think about how to resolve this issue effectively in C#; it's turning out to be a more tricky problem with the type system than I originally thought.

alana1 commented 8 years ago

Hello @bchavez, your suggestion worked. Thank you for your help on this.

bchavez commented 8 years ago

Hey @alana1 so I gave this a lot of thought. I really tried every trick in my book to think this one through for a clean performant implementation....

I decided that we're not going to support JObject in the RunChanges<JObject> run helper. The reasoning is because the generic type parameter open-endedness really complicates the code to check for nested JToken types. For example,

.RunChanges<JObject>()
.RunChanges<List<JObject>>()
.RunChanges<Tuple<JObject, JArray>>>()
... and on. and on.

So, I think the best we can do is document this behavior in the GOTCHA! and recommend that developers use .RunCursor<JObject>() instead of .RunChanges<JObject> as I've shown you above. .RunChanges<T> should really be only for POCO strongly typed conversions from JSON to T POCO.

:fire: :volcano: _"We're building it up, to break it back down..."_