Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NewtonSoft.Json custom JsonConverter deserialize to DateTime not working

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

like image 624
Manish Sinha Avatar asked Oct 31 '14 04:10

Manish Sinha


People also ask

Is it possible to convert JSON to date?

Technically this is invalid JSON according to the spec, but all browsers and some JSON frameworks, including Json.NET, support it. Note. From Json.NET 4.5 and onwards dates are written using the ISO 8601 format by default, and using this converter is unnecessary.

How are JSON converters chosen during serialization or deserialization?

During serialization or deserialization, a converter is chosen for each JSON element in the following order, listed from highest priority to lowest: [JsonConverter] applied to a property.

How do I set the default JSON converter for a class?

Apply the [JsonConverter] attribute to a class or a struct that represents a custom value type. Here's an example that makes the DateTimeOffsetJsonConverter the default for properties of type DateTimeOffset: Suppose you serialize an instance of the following type: Here's an example of JSON output that shows the custom converter was used:

What happens when you deserialize a JSON string into a stack<t> object?

If you deserialize a JSON string into a Stack<T> object and then serialize that object, the contents of the stack are in reverse order. This behavior applies to the following types and interface, and user-defined types that derive from them:


1 Answers

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

like image 195
Andrew Whitaker Avatar answered Oct 09 '22 12:10

Andrew Whitaker