5

I am trying to deserialize a Unix timestamp to a DateTime. In my case, I need to do much more checks before I can set a property to DateTime from a timestamp. If I use DateTime from Newtonsoft.Json it deserializes it to UTC time and I need to deserialize it to a specific timezone

The problem is that I am not able to get the correct time. It seems like my string to long parsing is failing. If I can get the long unix timestamp, I can get the rest of the logic working

I have a class named Alert

class Alert
{
    // Some properties

    [JsonConverter(typeof(UnixTimestampJsonConverter))]
    public DateTime Created { get; set; }

    // Some more properties
}

the class UnixTimestampJsonConverter is

class UnixTimestampJsonConverter : JsonConverter
{
    // Other override methods

    public override object ReadJson (JsonReader reader, Type objectType, 
        object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.EndObject)
            return null;

        if (reader.TokenType == JsonToken.StartObject) {
            long instance = serializer.Deserialize<long> (reader);
            return TimeUtils.GetCustomDateTime (instance);
        }

        return null;
    }
}

Where TimeUtils.GetCustomDateTime (instance) takes the long unixtimestamp and converts it into DateTime object of specific timezone.

I am in a PCL library with Profile 78, so I have limited access to System.TimeZoneInfo and I am using PCL version of NodaTime for other timezone calculations.


In case anyone is interested, this is the project on Github - MBTA Sharp

Manish Sinha
  • 2,092
  • 2
  • 22
  • 33
  • Could you try adding a `reader.Read();` right before the `Deserialize` line? I _think_ you're trying to deserialize the StartObject token since you're not advanding the reader. – Joachim Isaksson Oct 31 '14 at 04:57
  • I have been trying to [read this](http://stackoverflow.com/questions/8030538/how-to-implement-custom-jsonconverter-in-json-net-to-deserialize-a-list-of-base?rq=1) to understand what to do. Seems like my situation is much simpler than the one mentioned. Even if I did a `reader.Read ()`, shouldn't I still look for `StartObject` or should I look for `JsonToken.string`? – Manish Sinha Oct 31 '14 at 05:19
  • As far as I can see (can't really test atm) you're getting called with the reader pointing to the StartObject token, you need to advance it (using the Read call) to the actual value token before deserializing. Unsure if you need to advance it again to the EndObject token before returning. – Joachim Isaksson Oct 31 '14 at 05:25
  • I just expect a UNIX timestamp on that location, so can't I just use `reader.Value` and cast it to `long` and then go ahead? – Manish Sinha Oct 31 '14 at 05:42

1 Answers1

7

I'm pretty sure all you need to do is call serializer.Deserialize. Doing this will advance the reader correctly and you shouldn't need to do anything else:

public class UnixTimestampJsonConverter : JsonConverter
{
    public override object ReadJson(
        JsonReader reader,
        Type objectType,
        object existingValue,
        JsonSerializer serializer)
    {
        long ts = serializer.Deserialize<long>(reader);

        return TimeUtils.GetMbtaDateTime(ts);
    }

    public override  bool CanConvert(Type type)
    {
        return typeof(DateTime).IsAssignableFrom(type);
    }

    public override void WriteJson(
        JsonWriter writer,
        object value,
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanRead
    { 
        get { return true; } 
    }
}

Example: https://dotnetfiddle.net/Fa8Zis

Andrew Whitaker
  • 124,656
  • 32
  • 289
  • 307
  • Your solution works. It seems like my code had another problem. `Created` property was not being decorated with `[JsonProperty("created_dt")]` as the json key was `created_dt` whereas the name of the property is `Created` – Manish Sinha Oct 31 '14 at 19:31
  • Thanks @Andrew-whitaker I finally did manage to get it working. [This is the git commit](https://github.com/manish/mbta-sharp/commit/4e6ba2f6e98f5d11747622c249d820521bbff794) – Manish Sinha Oct 31 '14 at 19:43