我向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();
}
}
答案 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; }
}