2017-03-17 62 views
2

使用JsonConvert(expando, formatting, serializerSettings)時,可以忽略ExpandoObject屬性,特別是Delegate類型的屬性嗎?使用JSON.Net串行器設置忽略ExpandoObject屬性

基本上我試圖忽視的func屬性的所有分析在這個例子中的expando對象:

//{ 
// func:() => {} 
//} 
Action func =() => {}; 
dynamic expando = new ExpandoObject(); 
expando.func = func; 

// should be empty object {} 
string json = JsonConvert(expando, formatting, serializerSettings); 

我想的第一件事就是壓倒一切的轉換器。不幸的是,這不起作用,因爲我看到CanConvert遞歸調用ActionDelegateEntry→某些通用類型→RuntimeMethodInfo

private class ExpandoObjectIgnoreConverter : ExpandoObjectConverter 
    { 
     public override bool CanConvert(Type objectType) 
     { 
      if (typeof(Delegate).IsAssignableFrom(objectType)) 
      { 
       return false; 
      } 
      return base.CanConvert(objectType); 
     } 
    } 

一種在串行化設置和合約解析器中使用錯誤處理程序的方法。當我拋出錯誤時,將忽略該屬性的所有進一步處理,即Action DelegateEntry→某些通用類型→ RuntimeMethodInfo 。但是,如果可能的話,我希望比拋出異常更優雅。

錯誤處理程序:

 serializationSettings.Error = (sender, args) => 
     { 
      if (args.ErrorContext.Error is InvalidCastException) 
      { 
       args.ErrorContext.Handled = true; 
      } 
     } 

合同解析:

private class ExpandoObjectContractResolver : DefaultContractResolver 
    { 
     public override JsonContract ResolveContract(Type type) 
     { 
      if (typeof(Delegate).IsAssignableFrom(type)) 
      { 
       throw new InvalidCastException(); 
      } 
      else 
      { 
       return base.ResolveContract(type); 
      } 
     } 
    } 

我使用edge庫腳本從C#程序中的NodeJS。我試圖從C#中返回的javascript對象中刪除函數,因爲它們被分配了Delegate類型,與JsonConvert不匹配。

+1

我有點不清楚你的問題是什麼。當*序列化*時你試圖跳過委託值'ExpandoObject'屬性嗎?因爲這聽起來像是你試圖反序列化這個樣本json:'{ func:()=> {} }',這是無效的。 – dbc

+0

更新了該部分以使其更加清晰,這是在expando到json的序列化期間。 –

回答

2

ExpandoObjectConverter沒有任何自定義代碼到請寫ExpandoObject。相反,它會覆蓋JsonConverter.CanWrite以返回false,從而允許將expando一般序列化爲IDictionary<string, object>

因此您可以覆蓋CanWriteWriteJson()自己系列化之前過濾不需要的鍵/值對:

public class FilteredExpandoObjectConverter : ExpandoObjectConverter 
{ 
    public override bool CanWrite { get { return true; } } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var expando = (IDictionary<string, object>)value; 
     var dictionary = expando 
      .Where(p => !(p.Value is System.Delegate)) 
      .ToDictionary(p => p.Key, p => p.Value); 
     serializer.Serialize(writer, dictionary); 
    } 
} 

然後使用轉換器設置如下:

var formatting = Formatting.Indented; 
var serializerSettings = new JsonSerializerSettings 
{ 
    Converters = { new FilteredExpandoObjectConverter() }, 
}; 
var json = JsonConvert.SerializeObject(expando, formatting, serializerSettings); 

注意這隻會過濾器代表由ExpandoObject直接擁有的值。如果您的某個集合包含某些代理或某個POCO中的具有代表值的成員,那麼它們不會被此代碼過濾。

樣本fiddle

+0

很好的答案,謝謝你的幫助! –