2012-02-13 18 views
8

List<object> içinde bulunan DateTime örneklerini seri hale getirmek için System.Runtime.Serialization.Json.DataContractJsonSerializer sınıfını kullanmayla ilgili sorun yaşıyorum. Orijinal türüne yeniden serileştirmek için DateTime'ı alamıyorum. DataContractJsonSerializer, her zaman "/Date(1329159196126-0500)/" biçimindeki bir dize türüne dönüştürür. Eğer güçlü bir şekilde yazılan bir List<DateTime> kullanarak çalıştırmak eğer seri hale getirecek ve seriyi seri hale getirecek, ancak object basit bir liste veya dizi içinde karşılaşıldığında DateTimes tanımlamak ve düzgün bir şekilde serileştirmek için serializer almak için bir yol arıyorum.DataContractJsonSerializer - Listede Yerelleştirici DateTime <object>

DateTimes öğesinin, bu listenin içereceği ilkel ve dizelerin yanı tek türü olduğunu unutmayın. İşte bunu test etmek için kullanıyorum kod pasajı. DataContractJsonSerializer Eğer

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

cevap

7

Bu çok garip gibi görünüyor: serisini kaldırma sonra geri DateTime için

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

Dönüşüm: tarafından dizeye

Dönüşüm gibi

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

Yani bütün kod olurdu davranışı, benim tahminim, JS'de yeniden tanımlanmış bir tür olmadığından DateTime'dan kaynaklanıyor AÇIK. Ancak, seri hale getirme/serileştirme işlemini değiştirmek için kendi IDataContractSurrogate'nizi döndürebilirsiniz. 4.5 DataContractJsonSerializer bir sahiptir .NET Framework sürümünde

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<object> types 
      if (obj.GetType() == typeof(List<object>)) 
      { 
       var objList = (List<object>)obj; 

       List<object> copyList = new List<object>(); // 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<Type> 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; 
     } 
    } 
+1

Bu, temel olarak uyguladığım çözümdür. Teşekkürler. –

+0

1970'den önceki tarihleri ​​desteklemek için normal ifadeniz '/ Tarih \ ((-?) Olmalıdır.\ d +) ([- +]) (\ d +) \) /) ' –

4

bir zorunluluk değil, burada Json.Net kullanarak bir çözümdür.

var list = new List<object> { 27, "foo bar", 12.34m, true, DateTime.Now }; 

string json = JsonConvert.SerializeObject(list); 
var orgObj=JsonConvert.DeserializeObject<List<object>>(json); 

Bu Json dize olan

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

ve döndürülen Sen serileştirme önce bir dizeye DateTime.Now dönüştürebilirsiniz long, string, double, bool ve DateTime

3

olan türleri ve
geri dönüştürmek için DateT Deserialization sonra impe.

string dateAsString = Convert.ToString(DateTime.Now); 
    var list = new object[] { 27, "foo bar", 12.34m, true, dateAsString }; 

    var serializer = new DataContractJsonSerializer(typeof (List<object>)); 

    using (MemoryStream ms = new MemoryStream()) 
    { 
    serializer.WriteObject(ms, list); 
    ms.Position = 0; 
    var deserializedList = serializer.ReadObject(ms) as List<object>; 
    DateTime dateTime = Convert.ToDateTime(deserializedList[4]); 
    } 
30

:

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

Sonra bu sınıfı ekleyin: Bu kadar seri hale oluştururken

Bu örnek kodunu değiştirmek kullanmak için

var ser = new DataContractJsonSerializer(typeof(CreateOmsEntryCommand), 
       new DataContractJsonSerializerSettings 
       { 
        DateTimeFormat = new DateTimeFormat("yyyy-MM-dd'T'HH:mm:ssZ") 
       }); 
: DateTimeFormat ayarlamak için kullanılabilecek bir DataContractJsonSerializerSettings nesne kabul yapıcı
+2

Serileştirme açısından, 'DateTime' UTC’de ilk etapta bu işe yaramaz. Yerel zamanın, ama UTC'yi temsil eden 'Z' (okuma tarafında yanlış yorumlanmalıdır). Yyyy-MM-dd'T'HH: mm: ssK yerine kullanmak daha iyi olur. – Bruno

+1

Kabul ediyorum, yyyy-MM-dd'T'HH: mm: ssK veya yyyy-MM-dd'T'HH: mm: sszzz' kullanın. Yyyy-MM-dd'T'HH: mm: ssZ' kullanmayın. –

İlgili konular