Jsonシリアル化からプロパティを除外する方法


235

シリアル化するDTOクラスがあります

Json.Serialize(MyClass)

パブリックプロパティを除外するにはどうすればよいですか?

(コードのどこかで使用するため、公開する必要があります)


4
どのシリアル化フレームワークを使用していますか?
Pavel Gatilov

37
IgnoreDataMember ScriptIgnore JsonIgnore使用する
LB

3
[NonSerialized]属性も注目に値します。これはフィールドにのみ適用でき(プロパティには適用できません)、それ以外はJsonIgnoreと同じ効果があります。
Triynko 2016

Trynkoのコメントは非常に役に立ちます。フィールドでIgnoreDataMemberを使用すると、エラーは発生しませんが、適用されません。
Tillito 2018年

回答:


147

使用している場合はSystem.Web.Script.Serialization、.NETフレームワークの中で、あなたが置くことができるScriptIgnoreシリアル化されるべきではないメンバーに属性を。ここから取られた例を参照してください:

次の(簡略化された)ケースを考えます。

public class User {
    public int Id { get; set; }
    public string Name { get; set; }
    [ScriptIgnore]
    public bool IsComplete
    {
        get { return Id > 0 && !string.IsNullOrEmpty(Name); }
    } 
} 

この場合、IdプロパティとNameプロパティのみがシリアル化されるため、結果のJSONオブジェクトは次のようになります。

{ Id: 3, Name: 'Test User' }

PS。System.Web.Extensionsこれを機能させるには、「」への参照を追加することを忘れないでください


10
名前空間で見つかりましScriptIgnoreSystem.Web.Script.Serialization
Sorangwala Abbasali 2016

354

Json.Net属性[JsonIgnore]使用している場合は、シリアライズまたはデシリアライズ中にフィールド/プロパティを無視します。

public class Car
{
  // included in JSON
  public string Model { get; set; }
  public DateTime Year { get; set; }
  public List<string> Features { get; set; }

  // ignored
  [JsonIgnore]
  public DateTime LastModified { get; set; }
}

または、DataContractおよびDataMember属性を使用して、プロパティ/フィールドを選択的にシリアル化/非シリアル化できます。

[DataContract]
public class Computer
{
  // included in JSON
  [DataMember]
  public string Name { get; set; }
  [DataMember]
  public decimal SalePrice { get; set; }

  // ignored
  public string Manufacture { get; set; }
  public int StockCount { get; set; }
  public decimal WholeSalePrice { get; set; }
  public DateTime NextShipmentDate { get; set; }
}

詳細については、http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-sizeを参照してください


37
私がOPである場合は、選択した[ScriptIgnore]ソリューションよりもこの回答の方を好みます。主に、Jsonソリューションの合同性のため、Jsonの問題です。使用しているライブラリがソリューションを提供しているのに、なぜSystem.Web.Extensionsを使用するのですか?System.Runtime.Serializationは、Jsonを交換したい場合、すべてのシリアライザーと互換性があるはずなので、絶対的に最良のIMHOは[IgnoreDataMember]属性です。
スティーブH.

IgnoreDataMemberデフォルトのJsonResultシリアライザでは機能しません。
hendryanw

1
NewtonSoftは私を完全に助けてくれました。これにより、バックエンド専用のモデルから乱雑なプロパティが含まれることなく、jsonがきれいに見えます。
Sorangwala Abbasali 2016

1
@JCラジャどのように私は、このプロパティがnullの場合にのみdesalinizing中にプロパティを無視することができます
user123456

1
[NewtonSoft.Json]シリアライズのみを無視したい。次に、これに対する解決策はありますか?
チュオンコックカン

31

使用できます[ScriptIgnore]

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    [ScriptIgnore]
    public bool IsComplete
    {
        get { return Id > 0 && !string.IsNullOrEmpty(Name); }
    }
}

ここで参照

この場合、IDと名前はシリアル化されるだけです。


1
回答のURLが壊れています。である[ScriptIgnore]あなたのコントローラがベースMVCコントローラを使用している場合、このプロパティに使用すべきかreturn Json(...
Don Cheadle 2018年

2
古いコメントであることは承知していますが、はい、[ScriptIgnore]MVC Controller で使用します。ただし、SignalRを使用している場合は、使用する必要があり[JsonIgnore]ます。
サム

22

申し訳ありませんが、他の回答はどれも十分にコピー&ペーストできないため、別の回答を書くことにしました。

プロパティをいくつかの属性で装飾したくない場合、またはクラスにアクセスできない場合、または実行時にシリアル化するものなどを決定したい場合などは、Newtonsoft.Jsonでこれを行う方法を次に示します。

//short helper class to ignore some properties from serialization
public class IgnorePropertiesResolver : DefaultContractResolver
{
    private IEnumerable<string> _propsToIgnore;
    public IgnorePropertiesResolver(IEnumerable<string> propNamesToIgnore)
    {
        _propsToIgnore = propNamesToIgnore;
    }
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        property.ShouldSerialize = (x) => { return !_propsToIgnore.Contains(property.PropertyName); };
        return property;
    }
}

使用法

JsonConvert.SerializeObject(YourObject, new JsonSerializerSettings()
    { ContractResolver = new IgnorePropertiesResolver(new[] { "Prop1", "Prop2" }) };);

誰かが何かを追加したい場合に備えて、ここにコードを公開しました

https://github.com/jitbit/JsonIgnoreProps

重要な更新:ContractResolverこの回答を使用する場合は、オブジェクトをキャッシュしてください。そうしないと、パフォーマンスが低下する可能性があります。


15

私と同じように属性でコードを装飾する必要があることにそれほど熱心でない場合は、特にコンパイル時に何が起こるかがわからない場合は、私の解決策です。

JavaScriptシリアライザーの使用

    public static class JsonSerializerExtensions
    {
        public static string ToJsonString(this object target,bool ignoreNulls = true)
        {
            var javaScriptSerializer = new JavaScriptSerializer();
            if(ignoreNulls)
            {
                javaScriptSerializer.RegisterConverters(new[] { new PropertyExclusionConverter(target.GetType(), true) });
            }
            return javaScriptSerializer.Serialize(target);
        }

        public static string ToJsonString(this object target, Dictionary<Type, List<string>> ignore, bool ignoreNulls = true)
        {
            var javaScriptSerializer = new JavaScriptSerializer();
            foreach (var key in ignore.Keys)
            {
                javaScriptSerializer.RegisterConverters(new[] { new PropertyExclusionConverter(key, ignore[key], ignoreNulls) });
            }
            return javaScriptSerializer.Serialize(target);
        }
    }


public class PropertyExclusionConverter : JavaScriptConverter
    {
        private readonly List<string> propertiesToIgnore;
        private readonly Type type;
        private readonly bool ignoreNulls;

        public PropertyExclusionConverter(Type type, List<string> propertiesToIgnore, bool ignoreNulls)
        {
            this.ignoreNulls = ignoreNulls;
            this.type = type;
            this.propertiesToIgnore = propertiesToIgnore ?? new List<string>();
        }

        public PropertyExclusionConverter(Type type, bool ignoreNulls)
            : this(type, null, ignoreNulls){}

        public override IEnumerable<Type> SupportedTypes
        {
            get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { this.type })); }
        }

        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            var result = new Dictionary<string, object>();
            if (obj == null)
            {
                return result;
            }
            var properties = obj.GetType().GetProperties();
            foreach (var propertyInfo in properties)
            {
                if (!this.propertiesToIgnore.Contains(propertyInfo.Name))
                {
                    if(this.ignoreNulls && propertyInfo.GetValue(obj, null) == null)
                    {
                         continue;
                    }
                    result.Add(propertyInfo.Name, propertyInfo.GetValue(obj, null));
                }
            }
            return result;
        }

        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            throw new NotImplementedException(); //Converter is currently only used for ignoring properties on serialization
        }
    }

1
ロジックとのマイナーな変更をに変えるPropertyExclusionConverterことができますPropertyInclusionConverter
ザレフェス2015

これは素晴らしい
サイキランマンダーラ

これに関する潜在的な問題の1つは、オブジェクトがシリアル化されるたびに、名前の一致と除外の作業を何度も行わなければならないことです。ただし、コンパイルすると、タイプのプロパティは変更されません。これを、タイプごとに含めるべき名前を事前に計算し、各行のリストを再利用する必要があります。非常に大規模なJSONシリアル化ジョブの場合、キャッシングによりパフォーマンスに顕著な違いが生じる可能性があります。
ErikE 2017年

9

使用している場合は、を使用System.Text.Jsonできます[JsonIgnore]
FQ:System.Text.Json.Serialization.JsonIgnoreAttribute

公式Microsoftドキュメント:JsonIgnoreAttribute

ここで述べたように

ライブラリは、.NET Core 3.0共有フレームワークの一部として組み込まれています。
他のターゲットフレームワークの場合は、System.Text.Json NuGetパッケージをインストールします。パッケージは以下をサポートします:

  • .NET Standard 2.0以降のバージョン
  • .NET Framework 4.6.1以降のバージョン
  • .NET Core 2.0、2.1、および2.2

0

[NonSerialized]属性を使用することもできます

[Serializable]
public struct MySerializableStruct
{
    [NonSerialized]
    public string hiddenField;
    public string normalField;
}

MS docsから

シリアル化可能なクラスのフィールドをシリアル化しないことを示します。このクラスは継承できません。


たとえばUnityを使用している場合(これはUnityだけではありません)、これはUnityEngine.JsonUtility

using UnityEngine;

MySerializableStruct mss = new MySerializableStruct 
{ 
    hiddenField = "foo", 
    normalField = "bar" 
};
Debug.Log(JsonUtility.ToJson(mss)); // result: {"normalField":"bar"}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.