JSON
{
"title":"Mozilla Firefox",
"id":24,
"parent":2,
"dateAdded":1356753810000000,
"lastModified":1356753810000000,
"type":"text/x-moz-place-container",
"children":[]
}
C#
class Bookmark
{
public string title;
public string id;
[JsonProperty(ItemConverterType = typeof(JavaScriptDateTimeConverter))]
public DateTime dateAdded;
[JsonProperty(ItemConverterType = typeof(JavaScriptDateTimeConverter))]
public DateTime lastModified;
public string type;
public string root;
public long parent;
public List<Bookmark> children;
}
private static void Main(string[] args)
{
var json = File.ReadAllText(@"T:/bookmarks-2013-11-13.json");
var bookmarks = JsonConvert.DeserializeObject<Bookmark>(json);
}
当我尝试运行它时,我得到一个异常,
其他信息:读取日期错误。意外标记:整数。路径"添加日期"
我认为通过使用JavaScriptDateTimeConverter
,JSON.NET 可以弄清楚如何反序列化这些 unix 时间戳(自 epoch 以来
在查找有关转换器的文档时遇到问题...如果有必要,自己写一个可能不会太难。
编辑:这些实际上是微秒,而不是毫秒。
清理了一下 Cris的解决方案并实现了WriteJson
:
class Bookmark
{
public string title;
public long id;
[JsonConverter(typeof(MicrosecondEpochConverter))]
public DateTime dateAdded;
[JsonConverter(typeof(MicrosecondEpochConverter))]
public DateTime lastModified;
public string type;
public string root;
public long parent;
public List<Bookmark> children;
public string uri;
public override string ToString()
{
return string.Format("{0} - {1}", title, uri);
}
}
public class MicrosecondEpochConverter : DateTimeConverterBase
{
private static readonly DateTime _epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteRawValue(((DateTime)value - _epoch).TotalMilliseconds + "000");
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value == null) { return null; }
return _epoch.AddMilliseconds((long)reader.Value / 1000d);
}
}
internal class Program
{
private static void Main(string[] args)
{
var jsonString = File.ReadAllText(@"T:/bookmarks-2013-11-13.json");
var rootMark = JsonConvert.DeserializeObject<Bookmark>(jsonString);
var ret = JsonConvert.SerializeObject(rootMark);
}
}
有一种内置的方法可以从 unix 时间戳转换为 DateTime,而无需编写自己的类:
[JsonConverter(typeof(UnixDateTimeConverter))]
public DateTime lastModified;
https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Converters_UnixDateTimeConverter.htm
Cris的答案中的注释不正确,因为JavaScriptDateTimeConverter
是针对Date(52231943)
格式而不是OP中的Unix时间戳。
我意识到这个问题现在已经有几年了,所以自从这个问题被问到以来,很可能已经添加了这个类,但这可能有助于任何遇到相同问题的人。
您可以创建自定义日期时间转换器
var bookmarks = JsonConvert.DeserializeObject<Bookmark>(json,
new MyDateTimeConverter());
public class MyDateTimeConverter : Newtonsoft.Json.JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTime);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var t = long.Parse((string)reader.Value);
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(t);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
另一种方法是对类成员进行双重注释,
[JsonProperty(PropertyName="dateAdded")]
[JsonConverter(typeof(JavaScriptDateTimeConverter))]
public DateTime dateAdded;
根据接受的答案为.Net core和System.Text.Json
添加一个解决方案。在撰写本文时已在 3.1 中验证。
public class UnixDateTimeConverter : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return DateTime.UnixEpoch.AddSeconds(reader.GetInt64());
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue((value - DateTime.UnixEpoch).TotalMilliseconds + "000");
}
}
然后,您可以使用数据注释来应用它
[JsonConverter(typeof(UnixDateTimeConverter))]
public DateTime MyDateTime {get;set;}
嗯...棘手的一点是 DateTime 构造函数不接受时间戳作为参数。
这是本文的解决方案:如何将Unix时间戳转换为日期时间,反之亦然?
public static DateTime UnixTimeStampToDateTime( double unixTimeStamp )
{
// Unix timestamp is seconds past epoch
System.DateTime dtDateTime = new DateTime(1970,1,1,0,0,0,0);
dtDateTime = dtDateTime.AddSeconds( unixTimeStamp ).ToLocalTime();
return dtDateTime;
}
你必须调用它,最好在你的类中使用默认构造函数,或者让另一个属性在其get
方法中返回它。
与 Brian 的答案类似,这里有一个System.Text.Json
反序列化变体,它支持更多选项。
- Unix 时间以秒或毫秒为单位定义。假设:秒<年份> 1978 年。年份>
- 可为空的日期时间
public class UnixToNullableDateTimeConverter : JsonConverter<DateTime?>
{
public override bool HandleNull => true;
public bool? IsFormatInSeconds { get; set; } = null;
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TryGetInt64(out var time))
{
// if 'IsFormatInSeconds' is unspecified, then deduce the correct type based on whether it can be represented in the allowed .net DateTime range
if (IsFormatInSeconds == true || IsFormatInSeconds == null && time > _unixMinSeconds && time < _unixMaxSeconds)
return DateTimeOffset.FromUnixTimeSeconds(time).LocalDateTime;
return DateTimeOffset.FromUnixTimeMilliseconds(time).LocalDateTime;
}
return null;
}
public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) => throw new NotSupportedException();
private static readonly long _unixMinSeconds = DateTimeOffset.MinValue.ToUnixTimeSeconds() - DateTimeOffset.UnixEpoch.ToUnixTimeSeconds(); // -62_135_596_800
private static readonly long _unixMaxSeconds = DateTimeOffset.MaxValue.ToUnixTimeSeconds() - DateTimeOffset.UnixEpoch.ToUnixTimeSeconds(); // 253_402_300_799
}
这就是我的做法,它奏效了
在我的视图中模型我有一个日期时间类型的公共属性
Public DateTime TimeToBeShown {get; set;}
在我的模型中,我有 Long 类型的公共属性,它以 JSON 格式从 API 获取日期。
Public long DateThatIsComingAsJsonFormat {get; set;}
var dateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
TimeToBeShown=dateTime.AddSeconds(somethingfromloop.CreatedTime).ToLocalTime();
Bind to TimeToBeShown in Xaml