2011-11-07 56 views
2

我有一個已經序列化成JSON的類,並且我試圖將其反序列化爲一個對象。c#JavaScriptConverter - 如何反序列化自定義屬性?

例如

public class ContentItemViewModel 
{ 
    public string CssClass { get; set; } 
    public MyCustomClass PropertyB { get; set; } 
} 

簡單的財產(的CssClass)將與反序列化:

var contentItemViewModels = ser.Deserialize<ContentItemViewModel>(contentItems); 

但PropertyB得到一個錯誤......

我們添加了JavaScriptConverter:

ser.RegisterConverters(new List<JavaScriptConverter>{ publishedStatusResolver}); 

但是,當我們將'MyCustomClass'添加爲'SupportedType',Deserialize方法從未被調用過。但是,當我們將ContentItemViewModel作爲SupportedType時,則會調用Deserialize。

我們已經有了一個當前的解決方案,看起來是這樣的:

class ContentItemViewModelConverter : JavaScriptConverter 
{ 

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) 
    { 
     var cssClass = GetString(dictionary, "cssClass"); //I'm ommitting the GetString method in this example...   
     var propertyB= GetString(dictionary, "propertyB"); 

     return new ContentItemViewModel{ CssClass = cssClass , 
              PropertyB = new MyCustomClass(propertyB)} 
    } 

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) 
    { 
     throw new Exception("Only does the Deserialize"); 
    } 

    public override IEnumerable<Type> SupportedTypes 
    { 
     get 
     { 
      return new List<Type> 
       { 
        typeof(ContentItemViewModel) 
       }; 
     } 
    } 
} 

但我們寧願只反序列化MyCustomClass一個簡單的解決方案,因爲有一些其他領域的這些都對視圖模型,每次我們更改/添加屬性時,編輯此轉換器似乎是一種浪費......

是否有反序列化類型MyCustomClass的JUST PropertyB的方法?

感謝您的幫助!

回答

0

你有沒有使用DatacontractJsonSerializer

[DataContract] 
public class MyCustomClass 
{ 
    [DataMember] 
    public string foobar { get; set; } 
} 

[DataContract] 
public class ContentItemViewModel 
{ 
    [DataMember] 
    public string CssClass { get; set; } 
    [DataMember] 
    public MyCustomClass PropertyB { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 

     ContentItemViewModel model = new ContentItemViewModel(); 
     model.CssClass = "StackOver"; 
     model.PropertyB = new MyCustomClass(); 
     model.PropertyB.foobar = "Flow"; 

     //Create a stream to serialize the object to. 
     MemoryStream ms = new MemoryStream(); 

     // Serializer the User object to the stream. 
     DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ContentItemViewModel)); 
     ser.WriteObject(ms, model); 
     byte[] json = ms.ToArray(); 
     ms.Close(); 
     string s= Encoding.UTF8.GetString(json, 0, json.Length); 


     Console.ReadLine(); 
    } 
} 

添加所有可能的類DatacontractJsonSerializer.KnownTypes如果MyCustomClass具有推導考慮。

0

對於無論什麼它可能值得這一次,但我偶然發現了同樣的問題,並且解決方案是,反序列化程序還沒有得到關於你正在反序列化的類的線索,除非你給他必要的信息。

在頂層,它知道Deserialize <>()的類型參數的類型。這就是爲什麼你的轉換器ContentItemViewModel的作品。對於嵌套對象,它需要__type屬性和一個JavaScriptTypeResolver。

var ser = new JavaScriptSerializer(new SimpleTypeResolver()); 
ser.RegisterConverters(myconverters); 
MyClass myObject = new MyClass(); 
string json = ser.Serialize(myObject); 
    // set a breakpoint here to see what has happened 
ser.Deserialize<MyClass>(json); 

TypeResolver爲每個序列化對象添加__type屬性。您可以編寫使用短名稱的自定義類型解析器。在這個示例中,我使用.net中的SimpleTypeResolver「簡單地」將完全限定的類型名稱存儲爲__type。反序列化時,JavaScriptDeserializer找到__type並向TypeResolver詢問正確的類型。然後它知道一個類型並可以調用一個註冊的JavaScriptConverter.Deserialize方法。

如果沒有TypeResolver,對象將被反序列化爲字典,因爲JavaScriptSerializer沒有任何類型信息。

如果你不能在你的json字符串中提供一個__type屬性,我想你需要首先反序列化爲Dictionary,然後添加一個「猜測步驟」來解釋字段以找到正確的類型。然後,您可以使用JavaScriptSerializer的ConvertToType方法將字典複製到對象的字段和屬性中。

如果需要使用由ASP.NET提供,不能創建自己的JavaScriptSerializer,考慮JavaScriptSerializer的.ctor幫助本節:

所使用的JavaScriptSerializer的實例用於從客戶端腳本調用Web服務的異步通信層使用特殊類型的解析器。此類型解析器將可反序列化的類型限制爲Web服務的方法簽名中定義的類型,或者應用了GenerateScriptTypeAttribute的類型。您無法以編程方式修改此內置類型解析器。

也許GenerateScriptType屬性可以幫助你。但是我不知道這裏需要什麼樣的__type屬性。