2011-07-27 7 views
0

私のモデルにはEntity Frameworkが使用されており、JSONにシリアル化する必要があります。問題は、EFにはこれらの本当に素晴らしいナビゲーションコレクションが含まれていることです(たとえば、私のUserモデルにはOrdersプロパティがあります)。これらのオブジェクトをシリアライズするとき、シリアライザはこれらのコレクションの値を取得しようとします。配置されたコンテキストを使用するJavaScriptSerializerで特定のジェネリック型のプロパティを無視する方法はありますか?

ObjectContextインスタンスは削除されており、接続が必要な操作には使用できなくなりました。

私はシリアライザは放っておい作るために[ScriptIgnore]と私の性質を飾ることができます知っているが、それはこれらのプロパティのためのコードを生成するようEFに問題のthats。

シリアライザが汎用タイプEntityCollectionのプロパティをシリアル化しないようにする方法はありますか?<>

JSON.Netのような別の堅牢なjsonライブラリでこれを行う方法がありますか?

答えて

-2

JSON.NETを使用する場合は、JsonIgnoreなどの属性を使用して特定のプロパティを無視できます。私はNHibernateを介してロードされたオブジェクトをシリアル化するときにこの機能を使用します。

慣習を追加する可能性もあると思います。たぶんEFプロパティのフィルタを実装することができます。

+1

はちょうど確かに、これは一つの方法です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にいくつか変更が加えられました。 説明:一部の変更が再作成され、Fluentが有効になっています。 DeclaringTypeの代わりにPropertyTypeを使用するように少し修正しました。

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; 
    } 
} 

用法:JsonIgnore属性を追加する

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