2013-02-14 64 views
1

我們使用C#System.Runtime.Serialization.Json.DataContractJsonSerializer反序列化JSON。它適用於普通對象,但不適用於List。JSON反序列化列表<SomeObject>不起作用

例如,如果JSON字符串低於然後正常工作:

{"CacheInsertDateTime":"\/Date(1360761324878)\/","Data":{"__type":"SomeObject:#ConsoleApplication1","Symbol":"some string"}} 

但如果josn低於:

{"CacheInsertDateTime":"\/Date(1360761324878)\/","Data":[{"__type":"SomeObject:#ConsoleApplication1","Symbol":"some string"},{"__type":"SomeObject:#ConsoleApplication1","Symbol":"some other string"}]} 

的數據來作爲List<Object>List<SomeObject>。我附上了樣品解決方案,顯示了同樣的問題。任何幫助或方向表示讚賞。

編輯:添加的代碼

{

命名空間ConsoleApplication1 { 類節目 { /* Someobject類*/ [DataContract] 公共類SomeObject { 公共SomeObject(字符串符號) { this.Symbol = sym; } [DataMember] public string Symbol {get;組; }

} 
    /* Cahe Data */ 
    [DataContract()] 
    [KnownType("GetKnownTypes")] 
    class CacheData 
    { 
     [DataMember()] 
     public object Data { get; set; } 

     [DataMember()] 
     public DateTime CacheInsertDateTime { get; set; } 

     public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider) 
     { 
      return GetKnownTypes(); 
     } 
     public static IEnumerable<Type> GetKnownTypes() 
     { 
      if (knownTypes == null) 
      { 
       // Since reflection is costly, we will do the lookup once for the known types and persist the data in knownTypes variable 
       knownTypes = new List<Type>(); 

       // first add types from DataModel assembly get types which are marked with DataContract attribute 
       var typesInCurrentAssembly = Assembly.GetExecutingAssembly().GetTypes().Where 
        (t => t.GetCustomAttributes(false).Any(attrib => attrib is DataContractAttribute)); 
       foreach (var type in typesInCurrentAssembly) 
       { 
        // add type and list<type> also to the known types list 
        knownTypes.Add(type); 
        knownTypes.Add(typeof(List<>).MakeGenericType(type)); 
       } 

       knownTypes.Add(typeof(DataTable)); 
      } 
      return knownTypes; 
     } 
     private static List<Type> knownTypes = null; 
    } 

    /*Cache Response Class*/ 
    class CacheResponse<T> where T : class 
    { 
     public CacheData CacheData { get; set; } 
     public T Data 
     { 
      get{return (CacheData != null && CacheData.Data.GetType() == typeof(T)) ? CacheData.Data as T: null;} 
     } 
    } 
    /* Main class */ 
    static void Main(string[] args) 
    { 
     //1. first with someobject, it works same as above 
     string jsonString = "{\"CacheInsertDateTime\":\"\\/Date(1360761324878)\\/\",\"Data\":{\"__type\":\"SomeObject:#ConsoleApplication1\",\"Symbol\":\"some object 1\"}}"; 
     CacheData obj = null; 
     byte[] byteData = Encoding.UTF8.GetBytes(jsonString); 
     using (MemoryStream stream = new MemoryStream(byteData)) 
     { 
      var serializer = new DataContractJsonSerializer(typeof(CacheData)); 
      obj = serializer.ReadObject(stream) as CacheData; 
     } 
     CacheResponse<SomeObject> response1 = new CacheResponse<SomeObject>(); 
     response1.CacheData = obj; 
     SomeObject responseObj = response1.Data; //this response object is fine    

     //2. with list<someobject>, it does not work 
     jsonString = "{\"CacheInsertDateTime\":\"\\/Date(1360761324878)\\/\",\"Data\":[{\"__type\":\"SomeObject:#ConsoleApplication1\",\"Symbol\":\"some object 1\"},{\"__type\":\"SomeObject:#ConsoleApplication1\",\"Symbol\":\"some object 2\"}]}"; 
     byteData = Encoding.UTF8.GetBytes(jsonString); 
     using (MemoryStream stream = new MemoryStream(byteData)) 
     { 
      var serializer = new DataContractJsonSerializer(typeof(CacheData)); 
      obj = serializer.ReadObject(stream) as CacheData; 
     } 
     CacheResponse<List<SomeObject>> response2 = new CacheResponse<List<SomeObject>>(); 
     response2.CacheData = obj; 
     List<SomeObject> responseList = response2.Data;//this is null    
    } 
} 

}

+0

我找不到如何附加zip文件 – 2013-02-14 13:16:21

+0

「數據來作爲列表沒有列表」數據來作爲列表而不是列表。 – 2013-02-14 13:16:55

+0

注意:對於這些通用類型,請使用反標記:' – 2013-02-14 13:18:16

回答

0

確保讓串行知道將它傳遞給DataContractJsonSerializer構造會發生什麼類型的列表,例如。

以下示例按預期工作:

namespace ConsoleApplication1 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Diagnostics; 
    using System.IO; 
    using System.Runtime.Serialization.Json; 
    using System.Text; 

    public class SomeObject 
    { 
     public string Symbol { get; set; } 
    } 

    public class MyClass 
    { 
     public DateTime CacheInsertTime { get; set; } 
     public List<object> Data { get; set; } 
    } 

    public class Program 
    { 
     private const string JsonString = @"{""CacheInsertDateTime"":""\/Date(1360761324878)\/"",""Data"":[{""__type"":""SomeObject:#ConsoleApplication1"",""Symbol"":""some string""},{""__type"":""SomeObject:#ConsoleApplication1"",""Symbol"":""some other string""}]}"; 

     private static void Main() 
     { 
      var ser = new DataContractJsonSerializer(typeof (MyClass), new[] {typeof (SomeObject)}); 
      var ms = new MemoryStream(Encoding.ASCII.GetBytes(JsonString)); 

      var obj = (MyClass) ser.ReadObject(ms); 
      Trace.Assert(obj.Data.Count == 2); 
      Trace.Assert(((SomeObject) obj.Data[1]).Symbol == "some other string"); 
     } 
    } 
} 

注意我是怎麼過的typeof(SOMETYPE)到串行器的構造。

+0

我更新了我的代碼。我認爲整個問題是我們希望它是通用的,我們不能硬編碼類型[new [] {typeof(SomeObject)}]。 – 2013-02-14 13:49:24