web-dev-qa-db-ja.com

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

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

Test2Listnullの場合に限り、JsonIgnore()属性をTest2Listプロパティに追加します。それがnullでないならば、私は私のJSONにそれを含めたいです。

439
Amit

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
                            });
573
Mrchief

JsonProperty属性を使用した別の解決策:

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

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

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

746
sirthomas

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

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

モデルタイプに[DataContract][DataMember]を既に使用していて、JSON.NET固有の属性を追加したくない場合は、これが望ましいかもしれません。

51
Toby J

あなたは書くことができます:[JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

プロパティをデフォルト値で直列化しないようにします(nullだけではありません)。たとえば列挙型には便利です。

24

これを行うと、直列化しているオブジェクト内のすべてのnullを無視することができ、nullプロパティはJSONに表示されません。

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

彼らのサイト(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
// }
10

@ Mrchief's/@ amit's answerへの適応、しかしVBを使っている人へ

 Dim JSONOut As String = JsonConvert.SerializeObject(
           myContainerObject, 
           New JsonSerializerSettings With {
                 .NullValueHandling = NullValueHandling.Ignore
               }
  )

"オブジェクト初期化子:名前付き型と匿名型(Visual Basic)" /

https://msdn.Microsoft.com/ja-jp/library/bb385125.aspx

4
GlennG

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

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

これらのプロパティについては、JSONに := NullValueHandling.Include := NullValueHandling.Ignore のように変更したものではありません。ところで - 私はあなたがXMLとJSONの両方のシリアライゼーションのためのプロパティをうまく装飾することができることを発見しました(ちょうどそれらをちょうど隣同士に置く)。これにより、dotnetのXMLシリアライザまたはNewtonSoftシリアライザを自由に呼び出すことができます。どちらもサイドバイサイドで動作し、私の顧客はXMLまたはJSONを使用することができます。私は両方を必要とする顧客を持っているので、これはドアノブの上の目印のように滑らかです!

0
Destek

これは似たオプションですが、別の選択肢があります。

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

それから、私はこのようにそれを使います:

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

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

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

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


public void ConfigureServices(IServiceCollection services)

....

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

0
Hizzy

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"
 }
0
Rafy