DataContractJsonSerializer – 在List 中反序列化DateTime

我无法使用System.Runtime.Serialization.Json.DataContractJsonSerializer类来反序列化List包含的DateTime实例。 我似乎无法将DateTime反序列化为原始类型。 DataContractJsonSerializer始终将其反序列化为格式为"/Date(1329159196126-0500)/"的字符串类型。 如果我通过使用强类型List运行它,它将序列化和反序列化,但是我正在寻找方法让串行器在简单列表或object数组中遇到时识别并正确反序列化DateTimes。

请注意,DateTimes是此列表将包含的基元和字符串之外的唯一类型。 这是我用来测试它的代码片段。

 var list = new List { 27, "foo bar", 12.34m, true, DateTime.Now }; var serializer = new DataContractJsonSerializer(typeof (List)); using (MemoryStream ms = new MemoryStream()) { serializer.WriteObject(ms, list); ms.Position = 0; var deserializedList = serializer.ReadObject(ms) as List; } 

这似乎是非常奇怪的行为,我的猜测是它源于DateTime不是一个在JSON中被识别的类型。 但是,您可以滚动自己的IDataContractSurrogate来修改序列化/反序列化过程。

要使用此function,请在创建序列化程序时修改示例代码:

 var serializer = new DataContractJsonSerializer(typeof(List), null, int.MaxValue, false, new DateTimeDataContractSurrogate(), true); 

然后添加这个类:

 public class DateTimeDataContractSurrogate : IDataContractSurrogate { private static readonly Regex dateRegex = new Regex(@"/Date\((\d+)([-+])(\d+)\)/"); private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); public object GetCustomDataToExport(Type clrType, Type dataContractType) { // not used return null; } public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType) { // not used return null; } public Type GetDataContractType(Type type) { // not used return type; } public object GetDeserializedObject(object obj, Type targetType) { // for debugging //Console.WriteLine("GetDeserializedObject: obj = {0} ({1}), targetType = {2}", obj, obj.GetType(), targetType); // only act on List types if (obj.GetType() == typeof(List)) { var objList = (List)obj; List copyList = new List(); // a list to copy values into. this will be the list returned. foreach (var item in objList) { string s = item as string; if (s != null) { // check if we match the DateTime format Match match = dateRegex.Match(s); if (match.Success) { // try to parse the string into a long. then create a datetime and convert to local time. long msFromEpoch; if (long.TryParse(match.Groups[1].Value, out msFromEpoch)) { TimeSpan fromEpoch = TimeSpan.FromMilliseconds(msFromEpoch); copyList.Add(TimeZoneInfo.ConvertTimeFromUtc(epoch.Add(fromEpoch), TimeZoneInfo.Local)); continue; } } } copyList.Add(item); // add unmodified } return copyList; } return obj; } public void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection customDataTypes) { // not used } public object GetObjectToSerialize(object obj, Type targetType) { // for debugging //Console.WriteLine("GetObjectToSerialize: obj = {0} ({1}), targetType = {2}", obj, obj.GetType(), targetType); return obj; } public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData) { // not used return null; } public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit) { // not used return typeDeclaration; } } 

在.NET Framework 4.5版中, DataContractJsonSerializer有一个构造函数,它接受可用于设置DateTimeFormatDataContractJsonSerializerSettings对象:

 var ser = new DataContractJsonSerializer(typeof(CreateOmsEntryCommand), new DataContractJsonSerializerSettings { DateTimeFormat = new DateTimeFormat("yyyy-MM-dd'T'HH:mm:ssZ") }); 

如果DataContractJsonSerializer不是必须的 ,这里是使用Json.Net的解决方案。

 var list = new List { 27, "foo bar", 12.34m, true, DateTime.Now }; string json = JsonConvert.SerializeObject(list); var orgObj=JsonConvert.DeserializeObject>(json); 

这是Json字符串

 [27,"foo bar",12.34,true,"\/Date(1329161615596+0200)\/"] 

返回的类型有longstringdoubleboolDateTime

您可以在序列化之前将DateTime.Now转换为字符串
反序列化后将其转换回DateTime

转换为字符串:

 string dateAsString = Convert.ToString(DateTime.Now); 

反序列化后转换回DateTime:

 DateTime dateTime = Convert.ToDateTime(deserializedList[4]); 

所以整个代码就像:

  string dateAsString = Convert.ToString(DateTime.Now); var list = new object[] { 27, "foo bar", 12.34m, true, dateAsString }; var serializer = new DataContractJsonSerializer(typeof (List)); using (MemoryStream ms = new MemoryStream()) { serializer.WriteObject(ms, list); ms.Position = 0; var deserializedList = serializer.ReadObject(ms) as List; DateTime dateTime = Convert.ToDateTime(deserializedList[4]); }