2011-07-27 104 views
0

我對我的模型使用實體框架,我需要將它們序列化爲JSON。問題是,EF包含所有這些非常好的導航集合(例如我的用戶模型上有一個Orders屬性),當我去序列化這些對象時,序列化程序試圖獲取這些集合的值,並且EF試圖嘗試嘗試使用處置的上下文有沒有辦法讓JavaScriptSerializer忽略某個泛型類型的屬性?

ObjectContext實例已被處置,不能再用於需要連接的操作。

我知道我可以使用[ScriptIgnore]來修飾我的屬性,使序列化程序保持獨立,但這是EF的問題,因爲它會生成這些屬性的代碼。

有沒有辦法讓序列化程序不序列化屬性的泛型類型EntityCollection <>?

另外有沒有辦法做到這一點與另一個健壯的JSON庫如JSON.Net?

回答

-2

如果您使用JSON.NET,則可以使用JsonIgnore等屬性來忽略某些屬性。序列化通過NHibernate加載的對象時使用此功能。

我認爲還有可能會添加約定。也許你可以爲你的EF屬性實現一個過濾器。

+1

添加JsonIgnore屬性是幾乎一樣加入ScriptIgnore屬性 –

3

如果這個想法只是簡單地將這些對象返回給客戶端,那麼爲什麼不直接使用匿名類來返回所需的對象呢?

假設你有EntityFrameworkClass對象的這個醜陋的重列表,你可以這樣做:

var result = (from c in List<EntityFrameworkClass> 
      select new { 
         PropertyINeedOne=c.EntityFrameworkClassProperty1, 
         PropertyINeedTwo=c.EntityFrameworkClassProperty2 
       }).ToList(); 
+0

當然,這是一種方式。但是,由於我在這個應用程序中廣泛使用json,除了這些EF添加以外,模型可以很好地用於傳輸 –

+0

什麼是巧妙的解決方法!如果可以忽略JSON.NET與[JsonIgnore]一樣的效果,那會很棒,但是這個工作很有效,完全救了我! – SelAromDotNet

7

你可以聲明自定義的合同解析器指示要忽略的特性。這裏有一個通用的 「忽略」 的基礎上,the answer I found here

/// <summary> 
/// Special JsonConvert resolver that allows you to ignore properties. See https://stackoverflow.com/a/13588192/1037948 
/// </summary> 
public class IgnorableSerializerContractResolver : DefaultContractResolver { 
    protected readonly Dictionary<Type, HashSet<string>> Ignores; 

    public IgnorableSerializerContractResolver() { 
     this.Ignores = new Dictionary<Type, HashSet<string>>(); 
    } 

    /// <summary> 
    /// Explicitly ignore the given property(s) for the given type 
    /// </summary> 
    /// <param name="type"></param> 
    /// <param name="propertyName">one or more properties to ignore. Leave empty to ignore the type entirely.</param> 
    public void Ignore(Type type, params string[] propertyName) { 
     // start bucket if DNE 
     if (!this.Ignores.ContainsKey(type)) this.Ignores[type] = new HashSet<string>(); 

     foreach (var prop in propertyName) { 
      this.Ignores[type].Add(prop); 
     } 
    } 

    /// <summary> 
    /// Is the given property for the given type ignored? 
    /// </summary> 
    /// <param name="type"></param> 
    /// <param name="propertyName"></param> 
    /// <returns></returns> 
    public bool IsIgnored(Type type, string propertyName) { 
     if (!this.Ignores.ContainsKey(type)) return false; 

     // if no properties provided, ignore the type entirely 
     if (this.Ignores[type].Count == 0) return true; 

     return this.Ignores[type].Contains(propertyName); 
    } 

    /// <summary> 
    /// The decision logic goes here 
    /// </summary> 
    /// <param name="member"></param> 
    /// <param name="memberSerialization"></param> 
    /// <returns></returns> 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { 
     JsonProperty property = base.CreateProperty(member, memberSerialization); 

     if (this.IsIgnored(property.DeclaringType, property.PropertyName)) { 
      property.ShouldSerialize = instance => { return false; }; 
     } 

     return property; 
    } 
} 

與用法:

var jsonResolver = new IgnorableSerializerContractResolver(); 
// ignore single property 
jsonResolver.Ignore(typeof(Company), "WebSites"); 
// ignore single datatype 
jsonResolver.Ignore(typeof(System.Data.Objects.DataClasses.EntityObject)); 
var jsonSettings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = jsonResolver }; 
+0

什麼是DefaultContractResolver?似乎並不是System.Web.Script.Serialization – mike01010

+0

的一部分@ mike01010它是[JSON.NET]的一部分(http://james.newtonking.com/projects/json/help/index.html?主題= HTML/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor.htm) – drzaus

0

這是我的一點貢獻。對@drzaus的一些更改回答。 描述:一些resharped更改和Fluent啓用。稍微修復一下使用PropertyType而不是DeclaringType。

public class IgnorableSerializerContractResolver : DefaultContractResolver 
{ 
    protected readonly Dictionary<Type, HashSet<string>> Ignores; 

    public IgnorableSerializerContractResolver() 
    { 
     Ignores = new Dictionary<Type, HashSet<string>>(); 
    } 

    /// <summary> 
    /// Explicitly ignore the given property(s) for the given type 
    /// </summary> 
    /// <param name="type"></param> 
    /// <param name="propertyName">one or more properties to ignore. Leave empty to ignore the type entirely.</param> 
    public IgnorableSerializerContractResolver Ignore(Type type, params string[] propertyName) 
    { 
     // start bucket if DNE 
     if (!Ignores.ContainsKey(type)) 
      Ignores[type] = new HashSet<string>(); 

     foreach (var prop in propertyName) 
     { 
      Ignores[type].Add(prop); 
     } 

     return this; 
    } 

    /// <summary> 
    /// Is the given property for the given type ignored? 
    /// </summary> 
    /// <param name="type"></param> 
    /// <param name="propertyName"></param> 
    /// <returns></returns> 
    public bool IsIgnored(Type type, string propertyName) 
    { 
     if (!Ignores.ContainsKey(type)) return false; 

     // if no properties provided, ignore the type entirely 
     return Ignores[type].Count == 0 || Ignores[type].Contains(propertyName); 
    } 

    /// <summary> 
    /// The decision logic goes here 
    /// </summary> 
    /// <param name="member"></param> 
    /// <param name="memberSerialization"></param> 
    /// <returns></returns> 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     var property = base.CreateProperty(member, memberSerialization); 

     if (IsIgnored(property.PropertyType, property.PropertyName)) 
     { 
      property.ShouldSerialize = instance => false; 
     } 

     return property; 
    } 
} 

用法:

// Ignore by type, regardless property name 
var jsonResolver = new IgnorableSerializerContractResolver().Ignore(typeof(PropertyName)) 
var jsonSettings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = jsonResolver }; 
相關問題