2011-05-27 86 views
7

我想知道如何使用Json.NET庫排除/剝離給定類型(或其集合)的某些屬性被序列化爲? 我試圖寫我自己的合同解析器(繼承自DefaultContractResolver),但沒有運氣。JSON.NET - 在運行時排除特定類型的屬性

我知道我可以使用DataAnnotations來完成,與裝飾排除性能ScriptIgnoreAttribute,但它並不適用在我的情況。序列化的對象幾乎可以是任何東西,所以我不知道在設計時要排除哪些屬性。我知道只有類型屬性不應該序列化。

它看起來像一個相當簡單的任務,但不幸的是我找不到任何地方一個體面的解決辦法...

BTW - 我不是必然Json.NET庫 - 如果它可以很容易地使用默認的/其他的.NET JSON序列化器,這對我來說也是一個很好的解決方案。

UPDATE

性能有試圖序列之前被排除在外。爲什麼?

基本上,我正在接收的對象的類型和序列化可以具有從IDynamicMetaObjectProvider繼承的類型的動態屬性。我不打算來描述所有的細節,但DynamicMetaObjectGetMetaObject這些對象的方法返回沒有DynamicMetaObject.GetDynamicMemberNames方法來實現(拋出NotImplementedException ...)。 總結 - 問題是那些對象(我需要排除)不允許枚舉它們的屬性,Json.NET串行器在後臺嘗試做什麼。我總是以結束NotImplementedException被拋出。

+0

因此,要澄清,你想排除序列化屬性的值實現IDynamicMetaObjectProvider?我對動態類型非常熟悉,但我不確定你的實際序列化。這聽起來像是序列化普通類,並希望排除引用動態實例的某些屬性。同時你還表示你不知道正在序列化的項目的類型或基本類型 - 只是偶爾會引用動態的屬性而不能序列化。請發佈一個簡單的例子。 – 2011-05-27 17:27:30

+0

沒錯!我正在序列化的根對象可以是任何東西,但有時它可能有一個動態屬性(它引用一些IDynamicMetaObjectProvider對象或一些集合),我想從序列化中排除它。序列化對象不是動態的,只有排除的屬性是。 – 2011-05-27 17:37:18

+0

是否足以滿足您的需要,而不是完全排除這些屬性,而是將它們序列化爲空對象?因此,一個名爲Foo的屬性,它的實例是動態的,它將被序列化爲Foo:{} – 2011-05-27 18:42:46

回答

5

我已經嘗試了WCF JSON序列化以及System.Web.Script.Serialization.JavaScriptSerializer。我發現,如果你想要對序列化過程進行嚴格控制,並且不想被屬性和黑客束縛以使其工作,JavaScriptSerializer就是要走的路。它包含在.NET堆棧中,允許您創建並註冊JavaScriptConverter子類以執行類型的自定義序列化。

我發現可能會導致你一個問題的唯一限制是你不能輕易註冊一個轉換器來轉換Object(也就是說,一個轉換器的所有子類來統治它們全部)的所有子類。您確實需要了解公共基類或通過掃描程序集預先註冊該類型的集合。然而,屬性序列化完全由您決定,所以您可以決定使用簡單的反射序列化哪些屬性以及如何。

另外,JSON的缺省序列化要比WCF的方法好得多。默認情況下,所有類型都是不帶屬性的序列化,枚舉按名稱序列化,字符串鍵字典序列化爲JSON對象,列表序列化爲數組等等。但出於顯而易見的原因,例如圓形樹,甚至缺省行爲需要時間幫助時間。

在我的情況下,我支持的客戶端API與服務器類結構不完全匹配,我們想要一個簡單得多的JSON語法,並且每次都做到這一點。只要讓我知道你是否需要一些代碼示例來開始。

+0

@Jamie:感謝您的信息,但不幸的是我無法在設計時知道* serialized *對象的確切類型,因爲它們可以是任何東西。我只知道*不應該被序列化的確切類型* – 2011-05-27 13:43:07

+0

您是否需要爲在.NET框架本身中找到的所有類型執行自定義序列化,或者只需鍵入您自己引用的項目或程序集。如果是後者,您可以輕鬆地爲您的程序集中的所有類型註冊轉換器(不包括您選擇的排除項)。這可以像在註冊過程中傳遞類似assembly.GetTypes()。的地方那樣簡單(t => t.IsClass)。 – 2011-05-27 16:07:55

+0

@Jamie:應用程序具有模塊化結構,因此可以在運行時添加/刪除對象所來自的程序集。順便說一句,它看起來像一個矯枉過正的掃描所有程序集並收集所有類型只是爲了做簡單的JSON序列化。 – 2011-05-27 17:41:01

2

創建您自己的合約解析程序,重寫爲對象創建屬性的方法,然後過濾結果以僅包含您想要的結果。

+0

。我已經嘗試過,但無法讓它工作,因爲我需要在**序列化程序甚至試圖檢查它們之前排除某些屬性**。我需要排除的某些動態對象不允許枚舉它們的成員,並且如果嘗試的話會拋出異常。所以過濾結果是不會工作的...我相應地更新了問題。 – 2011-05-27 13:37:59

-1

您是否考慮過使用ShouldSerialize prefix屬性在運行時排除特定類型的屬性?

public class Employee 
{ 
    public string Name { get; set; } 
    public Employee Manager { get; set; } 

    public bool ShouldSerializeManager() 
    { 
    return (Manager != this); 
    } 
} 
+0

是的,但不幸的是這並沒有解決我的問題。它是關於不能選擇某些任意對象(在設計時不知道)的某些屬性(基於它們的類型)並將其排除在序列化之外。我只知道不應該被序列化的類型,沒有別的。 – 2012-06-30 02:30:13

相關問題