NewtonSoft.Json 自定义 Json 转换器反序列化 DateTime 无效

5

我试图将一个Unix时间戳反序列化为DateTime。在我的情况下,我需要在从时间戳设置属性为DateTime之前进行更多的检查。如果我使用来自Newtonsoft.JsonDateTime进行反序列化,它会将其反序列化为UTC时间,而我需要将其反序列化为特定时区。

问题是我无法获得正确的时间。似乎我的字符串转换为long失败了。如果我可以获取long Unix时间戳,我可以让剩余的逻辑工作起来。

我有一个名为Alert的类。

class Alert
{
    // Some properties

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

    // Some more properties
}

UnixTimestampJsonConverter 类是什么?

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;
    }
}
TimeUtils.GetCustomDateTime(instance) 将长整型的unix时间戳转换为特定时区的DateTime对象。我在一个PCL库中,使用的是Profile 78,所以对于System.TimeZoneInfo的访问有限,我正在使用NodaTime的PCL版本进行其他时区计算。如果有人感兴趣,这是Github上的项目- MBTA Sharp

你可以尝试在Deserialize行之前添加一个reader.Read();吗?我认为你正在尝试反序列化StartObject令牌,因为你没有推进阅读器。 - Joachim Isaksson
我一直在尝试理解如何做到读取此内容。看起来我的情况比提到的那个简单得多。即使我执行了reader.Read(),我是否仍然应该寻找StartObject或者应该寻找JsonToken.string - Manish Sinha
据我所见(目前无法真正测试),您正在使用指向StartObject令牌的读取器进行调用,您需要在反序列化之前将其推进(使用Read调用)到实际值令牌。不确定是否需要再次将其推进到EndObject令牌才能返回。 - Joachim Isaksson
我只需要在那个位置上的UNIX时间戳,所以我能不能只使用reader.Value并将其转换为long,然后继续进行? - Manish Sinha
1个回答

7
我非常确定您只需要调用serializer.Deserialize。 这样做将正确地推进阅读器,您不需要做任何其他操作。
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


你的解决方案可行。看起来我的代码有另一个问题。 Created 属性没有使用 [JsonProperty("created_dt")] 进行修饰,因为 json 键是 created_dt,而属性名称是 Created - Manish Sinha
感谢@Andrew-whitaker,我终于成功让它工作了。这是git提交记录 - Manish Sinha
@ManishSinha:太棒了!很高兴我能帮到你。 - Andrew Whitaker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接