Json.NET:将对象转换为DateTimeOffsets?

时间:2016-06-24 15:59:11

标签: c# .net json serialization json.net

我向API服务发出请求,该服务以下列形式返回日期为JSON:

{
     "dateCreated": {
        "date":8,
        "day":4,
        "hours":22,
        "minutes":44,
        "month":10,
        "nanos":241000000,
        "seconds":46,
        "time":1194590686241,
        "timezoneOffset":480,
        "year":107
     }
}

这里time是自Unix时代以来的毫秒数,因此它是我唯一想要注意的属性。

是否可以编写一个自定义Json.NET转换器,将其反序列化为

public class ApiResponse
{
    public ApiResponse(DateTimeOffset dateCreated)
    {
        DateCreated = dateCreated;
    }

    public DateTimeOffset DateCreated { get; }
}

(转换器会在对象的DateTimeOffset.FromUnixTimeMilliseconds属性上调用time。)

这是我到目前为止的代码:

public class ApiDateConverter : JsonConverter
{
    public override bool CanWrite => false;

    public override bool CanConvert(Type objectType)
    {
        return typeof(DateTimeOffset) == objectType;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // What type is existingValue here? How do I get existingValue.time?
    }

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

2 个答案:

答案 0 :(得分:1)

编写Json.Net转换器以将JSON直接转换为域对象肯定是可能,但我不建议这样做。

相反,我建议您创建一个镜像数据的DTO(数据传输对象):

public class DateDto
{
    public long Time { get; set; }
}

然后让Json.Net反序列化到这个对象中。

一旦你有了这个,你可以创建一个纯.Net转换器,将DateDto映射到DateTime或你想要的任何结构(假设你可能正在使用NodaTime库而不是.Net的DateTime)。

通过这样做,您可以省去实施自定义反序列化逻辑的麻烦,并且您遵循SOLID:单一责任原则中的 S 。您有一个对象,其目的仅仅是表示数据,还有一个转换器,用于将其转换为您的应用程序使用的任何内容。

它还提高了代码的可测试性。

答案 1 :(得分:1)

选项1 :您的ApiDateConverter可以通过以下方式填写:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        dynamic jObject = JObject.Load(reader);

        return DateTimeOffset.FromUnixTimeMilliseconds(jObject.time.Value);
    }

选项2 :不使用自定义转换器:

public class DateSerialized
{
    public int date { get; set; }
    public int day { get; set; }
    public int hours { get; set; }
    public int minutes { get; set; }
    public int month { get; set; }
    public int nanos { get; set; }
    public int seconds { get; set; }
    public long time { get; set; }
    public int timezoneOffset { get; set; }
    public int year { get; set; }
}

public class ApiResponse
{
    [JsonIgnore]
    public DateTimeOffset DateCreated => DateTimeOffset.FromUnixTimeMilliseconds(DateSerialized.time);

    [JsonProperty("dateCreated")]
    private DateSerialized DateSerialized { get; set; }
}