2011-07-27 114 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 }; 
相关问题