json.netを使用してnullの場合、クラスのプロパティを無視する方法


529

Json.NETを使用してクラスをJSONにシリアル化しています。

私はこのようなクラスを持っています:

class Test1
{
    [JsonProperty("id")]
    public string ID { get; set; }
    [JsonProperty("label")]
    public string Label { get; set; }
    [JsonProperty("url")]
    public string URL { get; set; }
    [JsonProperty("item")]
    public List<Test2> Test2List { get; set; }
}

私は追加したいJsonIgnore()に属性をTest2Listする場合にのみプロパティTest2Listですnull。nullでない場合は、jsonに含めます。

回答:


685

James Newton Kingによる:JavaScriptConvertを使用するのではなく、自分でシリアライザーを作成する場合、無視するように設定できるNullValueHandlingプロパティがあります。

これがサンプルです:

JsonSerializer _jsonWriter = new JsonSerializer {
                                 NullValueHandling = NullValueHandling.Ignore
                             };

または、@ amitによって提案された

JsonConvert.SerializeObject(myObject, 
                            Newtonsoft.Json.Formatting.None, 
                            new JsonSerializerSettings { 
                                NullValueHandling = NullValueHandling.Ignore
                            });

159
これは動作します:JsonConvert.SerializeObject(myObject、Newtonsoft.Json.Formatting.None、new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
アミット

それは私にとってはJsonSerializerSettingsうまくJsonSerializer
いき

1
重要なことの1つ-具象クラス(Person、Accountなど)でのみ機能します。辞書でこれを試したところ、うまく
いき

1
私は@ chester89と同じ問題を抱えています。ExpandoObjectでは、null値は無視されません。これはバグのようです(json.net 9.0.1を使用)
kwrl

2
答えが書かれたとき、JSON.Netは動的オブジェクトさえサポートしていませんでした。:)現時点では、カスタムコンバーターを使用して入札を行うことができます。
Mrchief

923

JsonProperty属性を使用した代替ソリューション:

[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
// or
[JsonProperty("property_name", NullValueHandling=NullValueHandling.Ignore)]

// or for all properties in a class
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]

このオンラインドキュメントで見られるように。


19
Json.net属性でクラスを汚染しないため、受け入れられた回答の方が優れています。
セルゲイ

117
@Sergeyそれはあなたのユースケースに依存します。(質問で述べたように)特定のプロパティに対してのみ使用したい場合は、これが正解です。グローバルな回答が必要な場合は、JsonSerializerでプロパティを設定する必要があります。
sibbl 2016年

同意-これはシンプルでエレガントです。価値のある投票。うまくいきます-シリアル化したいオブジェクトのプロパティをVBのNothingに設定するだけで、JSONの一部ではなくなります。ただし、これは文字列でのみ機能します。列挙型または整数型のプロパティは常に表示されます。Nothingに設定すると、デフォルト値は「0」になります。
Destek

3
@Destekでは、参照型フィールドをnullにできるようにする必要があります。そうすると、属性や設定を使用してシリアル化されなくなります。
トニー

1
多くの属性を持つクラスの「汚染」を回避するために、に処理ルールを割り当てることもできますが[JsonObject]、属性名が異なることに注意してください。[編集された回答]
Simon_Weaver

60

@sirthomasの回答と同様に、JSON.NETも次EmitDefaultValueプロパティを尊重ますDataMemberAttribute

[DataMember(Name="property_name", EmitDefaultValue=false)]

これは、モデルタイプですでに使用[DataContract]していて、[DataMember]JSON.NET固有の属性を追加したくない場合に適しています。


1
これはとても便利です!私はカスタムの例外クラスを設計していて、そこにJson.netのものを追加したくありませんでした。ありがとう!
jpgrassi

2
これは.Net Coreでは機能しませんでした。@sirthomasの回答をお勧めします:[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]を使用します
デリック

1
Newtonsoft.Json 10.0.2を使用した.Net Coreでは、これは問題なく動作します。
Karl-JohanSjögren2017

33

あなたは書ける: [JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

また、プロパティをデフォルト値(nullだけでなく)でシリアル化しないことも処理します。たとえば、列挙型に役立ちます。


3
これは、sirthomasの回答とまったく同じですが、なぜ追加したのですか?
OMGtechy 2017年

4
親切な情報として、DefaultValueHandlingとNullValueHandling ...には違いがあります
Vatsal Patel

4
それではあなたの答えでそれを説明できますか?一見、それは同じに見えますが、今あなたはそれが他の答えとどのように違うのか、どのようにそれを補完するのかについては述べていません。
OMGtechy 2017年

1
受け入れられた回答は状況によっては役立つ場合がありますが、常に使用できるとは限りません。これはちょうど医者が命じたものです。
メルボルン開発者、

1
これが欲しかったと思います。すべてではなく、特定のプロパティに対する特定の処理。
凍りつくような素晴らしい

23

これを行うと、シリアル化しているオブジェクトのすべてのnullを無視でき、nullプロパティはJSONに表示されなくなります

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
var myJson = JsonConvert.SerializeObject(myObject, settings);

12

彼らのサイトのこのリンクで見ることができるように(http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx)Iデフォルト値を指定するための[Default()]の使用をサポート

リンクから取得

   public class Invoice
{
  public string Company { get; set; }
  public decimal Amount { get; set; }

  // false is default value of bool
  public bool Paid { get; set; }
  // null is default value of nullable
  public DateTime? PaidDate { get; set; }

  // customize default values
  [DefaultValue(30)]
  public int FollowUpDays { get; set; }
  [DefaultValue("")]
  public string FollowUpEmailAddress { get; set; }
}


Invoice invoice = new Invoice
{
  Company = "Acme Ltd.",
  Amount = 50.0m,
  Paid = false,
  FollowUpDays = 30,
  FollowUpEmailAddress = string.Empty,
  PaidDate = null
};

string included = JsonConvert.SerializeObject(invoice,
  Formatting.Indented,
  new JsonSerializerSettings { });

// {
//   "Company": "Acme Ltd.",
//   "Amount": 50.0,
//   "Paid": false,
//   "PaidDate": null,
//   "FollowUpDays": 30,
//   "FollowUpEmailAddress": ""
// }

string ignored = JsonConvert.SerializeObject(invoice,
  Formatting.Indented,
  new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });

// {
//   "Company": "Acme Ltd.",
//   "Amount": 50.0
// }


3

.Net Coreでは、これがはるかに簡単になりました。startup.csにjsonオプションを追加するだけで、そこで設定を構成できます。


public void ConfigureServices(IServiceCollection services)

....

services.AddMvc().AddJsonOptions(options =>
{
   options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;               
});

1

Json.NET

 public class Movie
 {
            public string Name { get; set; }
            public string Description { get; set; }
            public string Classification { get; set; }
            public string Studio { get; set; }
            public DateTime? ReleaseDate { get; set; }
            public List<string> ReleaseCountries { get; set; }
 }

 Movie movie = new Movie();
 movie.Name = "Bad Boys III";
 movie.Description = "It's no Bad Boys";

 string ignored = JsonConvert.SerializeObject(movie,
            Formatting.Indented,
            new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

結果は次のようになります。

{
   "Name": "Bad Boys III",
   "Description": "It's no Bad Boys"
 }

1

System.Text.Jsonコア3.0および.NETこれは私のために働いていました:

var jsonSerializerOptions = new JsonSerializerOptions()
{
    IgnoreNullValues = true
};
var myJson = JsonSerializer.Serialize(myObject, jsonSerializerOptions );

0

GlennGの非常に役立つ回答(構文をC#からVB.Netに変換することは必ずしも「明白」ではない)を少し詳しく説明するために、個々のクラスプロパティを装飾してnull値の処理方法を管理することもできます。これを行う場合は、GlennGの提案によるグローバルJsonSerializerSettingsを使用しないでください。使用すると、個別の装飾が上書きされます。これは、JSONにnullアイテムを表示して、コンシューマーが特別な処理を行う必要がない場合に便利です。たとえば、コンシューマがオプションの項目の配列が通常利用可能であるが、現在は空であると知る必要がある場合...プロパティ宣言の装飾は次のようになります。

<JsonPropertyAttribute("MyProperty", DefaultValueHandling:=NullValueHandling.Include)> Public Property MyProperty As New List(of String)

JSONにまったく表示したくないプロパティについては、:= NullValueHandling.Include:= NullValueHandling.Ignoreに変更します。ちなみに、XMLとJSONの両方のシリアル化のプロパティを適切に装飾できることがわかりました(並べて配置するだけです)。これにより、dotnetまたはNewtonSoftシリアライザーでXMLシリアライザーを自由に呼び出すことができます-両方を並べて使用することも、私の顧客はXMLまたはJSONを使用することもできます。これはドアノブの鼻のように滑らかで、両方を必要とするお客様がいるためです。


0

同様のオプションがありますが、別の選択肢があります。

public class DefaultJsonSerializer : JsonSerializerSettings
{
    public DefaultJsonSerializer()
    {
        NullValueHandling = NullValueHandling.Ignore;
    }
}

次に、次のように使用します。

JsonConvert.SerializeObject(postObj, new DefaultJsonSerializer());

ここでの違いは次のとおりです。

  • インスタンス化と構成により、繰り返しコードを削減 JsonSerializerSettings使用される各場所をすること。
  • シリアル化するすべてのオブジェクトのすべてのプロパティを構成する時間を節約します。
  • 再利用可能なオブジェクトでプロパティを明示的に指定するのではなく、他の開発者にシリアル化オプションの柔軟性を提供します。
  • 私のユースケースは、コードがサードパーティのライブラリであり、私のクラスを再利用する開発者にシリアル化オプションを強制したくない場合です。
  • 潜在的な欠点は、他の開発者が知っておく必要のある別のオブジェクトであること、またはアプリケーションが小さい場合、このアプローチは単一のシリアル化では問題にならないことです。

-1
var settings = new JsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
settings.NullValueHandling = NullValueHandling.Ignore;
//you can add multiple settings and then use it
var bodyAsJson = JsonConvert.SerializeObject(body, Formatting.Indented, settings);

settings.NullValueHandling = NullValueHandling.Ignoreは他の回答でサジェストされています。明確ではありません。回答の
最新情報
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.