我正在尝试使用 JSON.Net 序列化为 BSON,但原始偏移量似乎没有得到遵守。
你能看出我如何努力使这项工作有问题吗?
[Test]
public void SerializeDateTimeOffsetToBson()
{
var serializer = new Newtonsoft.Json.JsonSerializer {
TypeNameHandling = TypeNameHandling.Auto,
DateParseHandling = DateParseHandling.DateTimeOffset,
DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind
};
var negOffset = new DateTimeOffset(2014, 7, 10, 0, 0, 0, new TimeSpan(-5, 0, 0));
var gmtOffset = new DateTimeOffset(2014, 7, 10, 0, 0, 0, new TimeSpan());
var posOffset = new DateTimeOffset(2014, 7, 10, 0, 0, 0, new TimeSpan(5, 0, 0));
var dt = new {
negOffset = negOffset,
gmtOffset = gmtOffset,
posOffset = posOffset
};
byte[] serialized;
using (var ms = new MemoryStream())
using (var writer = new BsonWriter(ms)) {
serializer.Serialize(writer, dt);
writer.Close();
serialized = ms.ToArray();
}
dynamic deserializedDt;
using (var ms = new MemoryStream(serialized))
using (var rdr = new BsonReader(ms)) {
deserializedDt = (dynamic)serializer.Deserialize(rdr);
rdr.Close();
}
Assert.IsTrue(deserializedDt.negOffset == dt.negOffset);
Assert.IsTrue(deserializedDt.posOffset == dt.posOffset);
Assert.IsTrue(deserializedDt.gmtOffset == dt.gmtOffset);
}
所有三个断言都会失败。
反序列化后,deserializedDt.negOffset
为 2014 年 7 月 9 日晚上 10 点,偏移量为 -07:00(计算机当前时区),deserializedDt.posOffset
为 7 月 9 日2014 年中午 12 点,偏移量为 -07:00,deserializedDt.gmtOffset
为 2014 年 7 月 9 日下午 5 点,偏移量为 -07:00。
在 .Net 4.0 项目中使用 JSON.Net 8.0.3。
更新--------------------
经过进一步调查,我在 Github 上提出了一个关于此的问题 https://github.com/JamesNK/Newtonsoft.Json/issues/898
最佳答案
BSON 规范不允许存储 DateTime 的偏移量; it stores UTC datetime as an Int64 , 自 Unix 纪元以来的毫秒数。
如果您不想丢失偏移量,您可以创建一个 JsonConverter,它将 DateTime 与偏移量分开,以分别序列化(和反序列化)两者。例如:
public class DateTimeOffsetConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(DateTimeOffset) == objectType;
}
public override object ReadJson(
JsonReader reader,
Type objectType,
object existingValue,
Newtonsoft.Json.JsonSerializer serializer)
{
if (reader.TokenType != JsonToken.StartObject)
return null;
reader.Read(); // PropertyName "DateTimeInTicks"
reader.Read(); // Property value
var ticks = (Int64)reader.Value;
reader.Read(); // PropertyName "Offset"
reader.Read(); // Property value
var offset = TimeSpan.Parse((String)reader.Value);
// Move forward to JsonToken.EndObject
reader.Read();
return new DateTimeOffset(ticks, offset);
}
public override void WriteJson(
JsonWriter writer,
object value,
Newtonsoft.Json.JsonSerializer serializer)
{
var dateTimeOffset = (DateTimeOffset)value;
var toSerialize = new {
DateTimeInTicks = dateTimeOffset.DateTime.Ticks,
Offset = dateTimeOffset.Offset
};
serializer.Serialize(writer, toSerialize);
}
}
然后您可以将它应用到您的类中,如下所示:
public class TestClass
{
public Int32 TestInt { get; set; }
[JsonConverter(typeof(DateTimeOffsetConverter))]
public DateTimeOffset TestDateTimeOffset { get; set; }
public String TestString { get; set; }
[JsonConverter(typeof(DateTimeOffsetConverter))]
public DateTimeOffset? TestNullableDateTimeOffset { get; set; }
}
关于JSON.Net BSON 序列化不正确地处理 DateTimeOffset?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36944671/