วิธีการเพิกเฉยคุณสมบัติในคลาสถ้าว่างโดยใช้ json.net


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หากไม่ใช่โมฆะฉันต้องการรวมไว้ใน json ของฉัน

คำตอบ:


685

ตาม James Newton King: หากคุณสร้าง serializer ด้วยตัวเองแทนที่จะใช้ 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, JsonSerializerSetSet ใหม่ {NullValueHandling = NullValueHandling.Ignore});
Amit

มันใช้งานได้สำหรับฉัน แต่ฉันJsonSerializerSettingsไม่ได้ใช้JsonSerializerเพราะมันแสดงว่ามีข้อผิดพลาดสำหรับล่าสุด
Yazan

1
สิ่งหนึ่งที่สำคัญ - ใช้ได้กับคลาสที่เป็นรูปธรรมเท่านั้น (บุคคลบัญชี ฯลฯ ) เมื่อฉันลองใช้พจนานุกรมนี้มันใช้ไม่ได้
chester89

1
ฉันมีปัญหาเช่นเดียวกับ @ chester89 ด้วย ExpandoObject ค่า null จะไม่ถูกละเว้น ดูเหมือนว่าจะเป็นข้อผิดพลาด (โดยใช้ json.net 9.0.1)
kwrl

2
เมื่อเขียนคำตอบแล้ว JSON.Net ก็ไม่สนับสนุนวัตถุแบบไดนามิก :) ในขณะนี้คุณสามารถใช้ตัวแปลงที่กำหนดเองเพื่อทำการเสนอราคาของคุณ
Mrchief

922

โซลูชันทางเลือกโดยใช้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
Sergey

117
@Sergey มันขึ้นอยู่กับกรณีการใช้งานของคุณ หากคุณต้องการให้มีเฉพาะคุณสมบัติ (ตามที่กล่าวไว้ในคำถาม) นี่คือคำตอบที่ถูกต้อง หากคุณต้องการคำตอบทั่วโลกคุณควรตั้งค่าคุณสมบัติใน JsonSerializer
sibbl

เห็นด้วย - นี่คือเรียบง่ายและสง่างาม การ upvoting ที่คุ้มค่า ใช้งานได้ดี - เพียงแค่ตั้งค่าคุณสมบัติในวัตถุที่คุณต้องการทำให้เป็นอันดับที่ไม่มีอะไรใน VB และจะไม่เป็นส่วนหนึ่งของ JSON อีกต่อไป สิ่งนี้จะใช้ได้กับสตริงเท่านั้น คุณสมบัติที่เป็น enums หรือจำนวนเต็มจะปรากฏขึ้นเสมอ - การตั้งค่าเป็นไม่มีผลลัพธ์จะมีค่าเริ่มต้นเป็น "0"
Destek

3
@Destek คุณต้องทำให้ฟิลด์ประเภทการอ้างอิงเป็นโมฆะจากนั้นจะไม่ถูกทำให้เป็นอนุกรมโดยใช้แอตทริบิวต์หรือการตั้งค่า
Tony

1
เพื่อหลีกเลี่ยง 'สร้างมลภาวะ' คลาสของคุณด้วยแอ็ตทริบิวต์มากมายคุณยังสามารถกำหนดกฎการจัดการ[JsonObject]ได้ แต่โปรดทราบว่าชื่อแอททริบิวนั้นแตกต่างกัน [คำตอบแก้ไข]
Simon_Weaver

60

คล้ายกับคำตอบ @ sirthomas ของ JSON.NET ยังเคารพคุณสมบัติใน:EmitDefaultValueDataMemberAttribute

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

สิ่งนี้อาจเป็นที่ต้องการหากคุณกำลังใช้[DataContract]และ[DataMember]อยู่ในประเภทรุ่นของคุณอยู่แล้วและไม่ต้องการเพิ่มแอตทริบิวต์เฉพาะของ JSON.NET


1
สิ่งนี้มีประโยชน์มาก! ฉันกำลังออกแบบคลาส Exception ที่กำหนดเองและฉันไม่ต้องการเพิ่มสิ่ง Json.net ในนั้น ขอบคุณ!
jpgrassi

2
สิ่งนี้ไม่ทำงานใน. Net Core แนะนำ @sirthomas คำตอบ: ใช้ [JsonProperty (NullValueHandling = NullValueHandling.Ignore)]
Derrick

1
มันใช้งานได้ดีสำหรับฉันใน. Net Core กับ Newtonsoft.Json 10.0.2
Karl-Johan Sjögren

33

คุณสามารถเขียน: [JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

นอกจากนี้ยังดูแลคุณสมบัติที่ไม่เป็นอนุกรมที่มีค่าเริ่มต้น (ไม่เฉพาะ null) มันจะมีประโยชน์สำหรับ enums เช่น


3
นี่เป็นคำตอบเดียวกับ sirthomas ทำไมคุณถึงเพิ่มเข้าไป
OMGtechy

4
สำหรับข้อมูลชนิดของคุณมีความแตกต่างระหว่าง DefaultValueHandling และ NullValueHandling ...
Vatsal Patel

4
คุณช่วยอธิบายมันในคำตอบของคุณได้ไหม? เมื่อมองแวบแรกมันก็เหมือนกันและตอนนี้คุณพูดถึงแล้วว่ามันไม่ได้บอกว่ามันแตกต่างจากคำตอบอื่น ๆ / ดูว่ามันเป็นอย่างไร
OMGtechy

1
แม้ว่าคำตอบที่ได้รับการยอมรับอาจมีประโยชน์ในบางสถานการณ์ แต่ก็ไม่สามารถใช้งานได้เสมอไป นี่เป็นเพียงสิ่งที่แพทย์สั่ง
นักพัฒนาเมลเบิร์น

1
ฉันคิดว่านี่คือสิ่งที่ฉันต้องการ การจัดการเฉพาะกับคุณสมบัติบางอย่างไม่ใช่ทั้งหมด
frostymarvelous

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

4

การปรับให้เข้ากับคำตอบของ @ Mrchief's / @ amit แต่สำหรับคนที่ใช้ VB

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

ดู: "วัตถุเริ่มต้น: ชื่อและประเภทไม่ระบุชื่อ (Visual Basic)"

https://msdn.microsoft.com/en-us/library/bb385125.aspx


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และ. NET Core 3.0 สิ่งนี้ใช้ได้สำหรับฉัน:

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

0

ในการอธิบายคำตอบที่เป็นประโยชน์ของ GlennG เล็กน้อย (การแปลไวยากรณ์จาก C # เป็น VB.Net นั้นไม่ใช่ "ชัดเจน" เสมอไป) คุณยังสามารถตกแต่งคุณสมบัติของคลาสแต่ละตัวเพื่อจัดการวิธีจัดการค่าที่ไม่เป็นประโยชน์ หากคุณทำเช่นนี้อย่าใช้ JsonSerializerSettings ทั่วโลกจากคำแนะนำของ GlennG มิฉะนั้นจะแทนที่การตกแต่งส่วนบุคคล สิ่งนี้มีประโยชน์ถ้าคุณต้องการให้รายการ null ปรากฏใน JSON เพื่อให้ผู้บริโภคไม่ต้องจัดการอะไรเป็นพิเศษ ตัวอย่างเช่นหากผู้บริโภคจำเป็นต้องรู้ว่าอาร์เรย์ของรายการที่เป็นตัวเลือกนั้นปกติแล้วจะว่าง แต่ขณะนี้ว่างเปล่า ... การตกแต่งในการประกาศคุณสมบัติมีลักษณะดังนี้:

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

สำหรับคุณสมบัติที่คุณไม่ต้องการที่จะมีปรากฏที่ทุกคนในการเปลี่ยนแปลง JSON = NullValueHandling.Includeไป: = NullValueHandling.Ignore โดยวิธีการ - ฉันพบว่าคุณสามารถตกแต่งสถานที่ให้บริการสำหรับทั้ง XML และ JSON เป็นอันดับที่ดี (เพียงวางไว้ติดกัน) สิ่งนี้ทำให้ฉันมีตัวเลือกในการโทร XML serializer ใน dotnet หรือ NewtonSoft serializer ตามใจ - ทั้งการทำงานเคียงข้างกันและลูกค้าของฉันมีตัวเลือกในการทำงานกับ 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 ถูก sugested ในคำตอบอื่น ๆ ไม่ชัดเจนมีอะไรใหม่ในคำตอบของคุณ
Michael Freidgeim
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.