2013-05-31 98 views
2

我使用Json.Net序列化/反序列化一個具有System.Text.Encoding類型屬性的類。嘗試了一個簡單的測試,我的序列化的類沒有任何問題:有沒有更好的方式來處理Json.Net的編碼值?

public class TestClass { 
    public Encoding TheEncoding { get; set; } 
} 

var testClass = new TestClass { TheEncoding = Encoding.UTF8 }; 
var json = JsonConvert.SerializeObject(testClass, Formatting.Indented); 
var obj = JsonConvert.DeserializeObject<TestClass>(json); 

序列化爲:

{ 
    "TheEncoding": { 
    "BodyName": "utf-8", 
    "EncodingName": "Unicode (UTF-8)", 
    "HeaderName": "utf-8", 
    "WebName": "utf-8", 
    "WindowsCodePage": 1200, 
    "IsBrowserDisplay": true, 
    "IsBrowserSave": true, 
    "IsMailNewsDisplay": true, 
    "IsMailNewsSave": true, 
    "IsSingleByte": false, 
    "EncoderFallback": { 
     "DefaultString": "?", 
     "MaxCharCount": 1 
    }, 
    "DecoderFallback": { 
     "DefaultString": "?", 
     "MaxCharCount": 1 
    }, 
    "IsReadOnly": true, 
    "CodePage": 65001 
    } 
} 

但是,反序列化的時候,我得到了一個例外:

無法創建System.Text.Encoding類型的實例。 Type是一個 接口或抽象類,不能實例化。路徑 「TheEncoding.BodyName」,3號線,位置16

我能夠通過創建一個處理System.Text.Encoding類型的定製轉換器讓過去這個問題:

public class JsonEncodingConverter : JsonConverter { 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { 
     // Serialize as the BodyName. 
     serializer.Serialize(writer, (value as Encoding).BodyName); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { 
     // Already good to go. 
     return existingValue; 
    } 

    public override bool CanConvert(Type objectType) { 
     return (typeof (Encoding).IsAssignableFrom(objectType)); 
    } 
} 

var testClass = new TestClass { TheEncoding = Encoding.UTF8 }; 
var json = JsonConvert.SerializeObject(testClass, Formatting.Indented, new JsonEncodingConverter()); 
var obj = JsonConvert.DeserializeObject<TestClass>(json , new JsonEncodingConverter()); 

現在定製轉換序列化生產:

{ 
    "TheEncoding": "utf-8" 
} 

當使用自定義轉換器反序列化JSON這樣可以成功往返式操作回原來的對象。

我是Json.Net的新手,我有一種強烈的感覺,我這樣做很難!當然,處理System.Text.Encoding有一個更好更少涉及的方法?

回答

2

使用[DataContract][DataMember]屬性來明確設置哪些屬性將在您的TestClass對象上被序列化。

  1. 忽略TheEncoding屬性中的屬性。
  2. 創建一個幫助屬性,將其序列化爲「utf-8」(具體取決於TheEncoding的值)。在此屬性中包含[DataMember]屬性。

例如:

[DataContract] 
public class TestClass 
{ 
    public Encoding TheEncoding { get; set; } 

    [DataMember] 
    public string TheEncodingName 
    { 
    get 
    { 
     if (this.TheEncoding == System.Text.Encoding.UTF8) 
     return "utf-8"; 
     // TODO: More possibilities 
    } 
    set 
    { 
     if (value == "utf-8") 
     this.TheEncoding = System.Text.Encoding.UTF8; 
     // TODO: More possibilities 
    } 
    } 
} 

當串行化,TheEncoding將被跳過並且TheEncodingName將被代替序列化。

+0

很明顯,我不僅是Json.Net的新手,而且是一般的.Net序列化。謝謝,那就是訣竅! – Darryl

0

我認爲解決這個問題的更好方法是找出你的JSON對象需要什麼屬性?

服務器端沒有理由包含來自Encoding對象的所有屬性,因爲您已在運行時作爲.NET框架的一部分訪問它。

在客戶端我無法想象爲什麼你需要從Encoding對象的所有屬性。

發送EncodingNameBodyName可能更直觀,並且您可以確定要在服務器上使用哪種編碼對象。

作爲一個例子,如果我要發送一些JSON到服務器指定utf-8我會知道使用Encoding.UTF8

相關問題