Cách bỏ qua một thuộc tính trong lớp nếu null, sử dụng json.net


529

Tôi đang sử dụng Json.NET để tuần tự hóa một lớp thành JSON.

Tôi có lớp học như thế này:

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

Tôi muốn thêm một JsonIgnore()thuộc tính cho Test2Listtài sản chỉ khi Test2Listnull. Nếu nó không phải là null thì tôi muốn đưa nó vào json của tôi.

Câu trả lời:


685

Theo James Newton King: Nếu bạn tự tạo serializer thay vì sử dụng JavaScriptConvert, có một thuộc NullValueHandlingtính mà bạn có thể đặt để bỏ qua.

Đây là một mẫu:

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

Ngoài ra, theo đề xuất của @amit

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

159
Công việc này: JsonConvert.SerializeObject (myObject, Newtonsoft.Json.Formatted.None, new JsonSerializerSinstall {NullValueHandling = NullValueHandling.Ignore});
Amit

nó làm việc cho tôi nhưng tôi đã JsonSerializerSettingskhông sử dụng JsonSerializervì nó đã báo lỗi cho người cuối cùng
Yazan

1
một điều quan trọng - nó chỉ hoạt động với các lớp cụ thể (Người, Tài khoản, v.v.). Khi tôi thử cái này với Dictionary, nó không hoạt động
chester89

1
Tôi có cùng một vấn đề như @ chester89. Với một giá trị null ExpandoObject không được bỏ qua. Đó dường như là một lỗi (sử dụng json.net 9.0.1)
kwrl

2
Khi câu trả lời được viết, JSON.Net thậm chí không hỗ trợ các đối tượng động. :) Hiện tại, bạn có thể sử dụng trình chuyển đổi tùy chỉnh để thực hiện đấu thầu.
Ông trùm

923

Một giải pháp thay thế bằng cách sử dụng JsonPropertythuộc tính:

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

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

Như đã thấy trong tài liệu trực tuyến này .


19
Câu trả lời được chấp nhận là tốt hơn vì nó không gây ô nhiễm các lớp của bạn với các thuộc tính Json.net.
Sergey

117
@Sergey nó phụ thuộc vào trường hợp sử dụng của bạn. Nếu bạn chỉ muốn có nó cho các thuộc tính cụ thể (như được đề cập trong câu hỏi), thì đây là câu trả lời chính xác. Nếu bạn muốn có câu trả lời toàn cầu, bạn nên đặt thuộc tính trong JsonSerializer.
sibbl

Đồng ý - đây là đơn giản và thanh lịch. Đáng để nâng cao. Hoạt động rất tốt - chỉ cần đặt một thuộc tính trong đối tượng bạn muốn tuần tự hóa thành Không có gì trong VB và nó không còn là một phần của JSON. Điều này sẽ chỉ hoạt động với String mặc dù. Các thuộc tính là số nguyên hoặc số nguyên sẽ luôn hiển thị - cài đặt thành Không có kết quả trong giá trị mặc định là "0" bất kể.
Destek

3
@Destek bạn cần làm cho các trường loại tham chiếu trở thành null, sau đó chúng sẽ không được tuần tự hóa bằng cách sử dụng thuộc tính hoặc cài đặt.
Tony

1
Để tránh 'gây ô nhiễm' các lớp của bạn với nhiều thuộc tính, bạn cũng có thể gán quy tắc xử lý trên [JsonObject], nhưng lưu ý rằng tên thuộc tính là khác nhau. [câu trả lời được chỉnh sửa]
Simon_Weaver

60

Tương tự như câu trả lời của @ sirthomas, JSON.NET cũng tôn trọng thuộc EmitDefaultValuetính trên DataMemberAttribute:

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

Điều này có thể được mong muốn nếu bạn đã sử dụng [DataContract][DataMember]trong loại mô hình của mình và không muốn thêm các thuộc tính dành riêng cho JSON.NET.


1
Điều này rất hữu ích! Tôi đã thiết kế một lớp Exception tùy chỉnh và tôi không muốn thêm công cụ Json.net vào đó. Cảm ơn!
jpgrassi

2
Điều này không hoạt động trong .Net Core. Giới thiệu câu trả lời @sirthomas: sử dụng [JsonProperty (NullValueHandling = NullValueHandling.Ignore)]
Derrick

1
Nó hoạt động tốt với tôi trong .Net Core với Newtonsoft.Json 10.0.2.
Karl-Johan Sjögren

33

Bạn có thể viết: [JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

Nó cũng quan tâm đến việc không tuần tự hóa các thuộc tính với các giá trị mặc định (không chỉ null). Nó có thể hữu ích cho enums chẳng hạn.


3
Điều này giống hệt như câu trả lời của sirthomas, tại sao bạn lại thêm nó?
OMGtechy

4
Đối với thông tin loại của bạn, có sự khác biệt giữa DefaultValueHandling và NullValueHandling ...
Vatsal Patel

4
Bạn có thể giải thích nó trong câu trả lời của bạn sau đó? Thoạt nhìn, nó trông giống nhau, và bây giờ bạn đã đề cập rằng, nó không nói rõ điều này khác với câu trả lời khác như thế nào / nó khen như thế nào.
OMGtechy

1
Mặc dù câu trả lời được chấp nhận có thể hữu ích trong một số trường hợp, nhưng không phải lúc nào cũng có thể sử dụng nó. Đây chỉ là những gì bác sĩ đã ra lệnh.
Nhà phát triển Melbourne

1
Tôi nghĩ rằng đây là những gì tôi muốn. Xử lý cụ thể trên các thuộc tính nhất định, không phải tất cả.
sương giá

23

Bạn có thể làm điều này để bỏ qua tất cả các null trong một đối tượng bạn đang tuần tự hóa và mọi thuộc tính null sẽ không xuất hiện trong JSON

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

12

Như có thể thấy trong liên kết này trên trang web của họ (http://james.newtonking.com/archive/2009/10/23/ffic-json-with-json-net-reducing-serialized-json-size.aspx) Tôi hỗ trợ sử dụng [Mặc định ()] để chỉ định giá trị mặc định

Lấy từ liên kết

   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

Trong .Net Core, điều này bây giờ dễ dàng hơn nhiều. Trong startup.cs của bạn chỉ cần thêm tùy chọn json và bạn có thể định cấu hình cài đặt ở đó.


public void ConfigureServices(IServiceCollection services)

....

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

1

Với 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 });

Kết quả sẽ là:

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

1

Với System.Text.Jsonvà .NET Core 3.0, điều này làm việc với tôi:

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

0

Để giải thích một chút về câu trả lời rất hữu ích của GlennG (dịch cú pháp từ C # sang VB.Net không phải lúc nào cũng "rõ ràng"), bạn cũng có thể trang trí các thuộc tính lớp riêng lẻ để quản lý cách xử lý các giá trị null. Nếu bạn làm điều này, đừng sử dụng JsonSerializerSinstall toàn cầu từ đề xuất của GlennG, nếu không nó sẽ ghi đè lên các trang trí riêng lẻ. Điều này rất hữu ích nếu bạn muốn một mục null xuất hiện trong JSON để người tiêu dùng không phải thực hiện bất kỳ xử lý đặc biệt nào. Ví dụ, nếu người tiêu dùng cần biết một loạt các mặt hàng tùy chọn thường có sẵn, nhưng hiện đang trống ... Trang trí trong tờ khai tài sản trông như thế này:

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

Đối với những thuộc tính mà bạn không muốn xuất hiện ở tất cả trong thay đổi JSON : = NullValueHandling.Include to : = NullValueHandling.Ignore . Nhân tiện - tôi đã thấy rằng bạn có thể trang trí một thuộc tính cho cả tuần tự hóa XML và JSON tốt (chỉ cần đặt chúng ngay cạnh nhau). Điều này cho tôi tùy chọn gọi trình tuần tự hóa XML bằng dotnet hoặc trình tuần tự hóa NewtonSoft theo ý muốn - cả hai hoạt động song song và khách hàng của tôi có tùy chọn để làm việc với XML hoặc JSON. Điều này là trơn tru như snot trên một tay nắm cửa vì tôi có khách hàng yêu cầu cả hai!


0

Đây là một tùy chọn tương tự, nhưng cung cấp một lựa chọn khác:

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

Sau đó, tôi sử dụng nó như thế này:

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

Sự khác biệt ở đây là:

  • Giảm mã lặp lại bằng cách khởi tạo và cấu hình JsonSerializerSettings từng nơi được sử dụng.
  • Tiết kiệm thời gian trong việc cấu hình mọi thuộc tính của mọi đối tượng sẽ được tuần tự hóa.
  • Vẫn cho phép các nhà phát triển khác linh hoạt trong các tùy chọn tuần tự hóa, thay vì có thuộc tính được chỉ định rõ ràng trên một đối tượng có thể sử dụng lại.
  • Trường hợp sử dụng của tôi là mã là thư viện của bên thứ 3 và tôi không muốn buộc các tùy chọn tuần tự hóa đối với các nhà phát triển muốn sử dụng lại các lớp của tôi.
  • Hạn chế tiềm năng là đó là một đối tượng khác mà các nhà phát triển khác sẽ cần biết hoặc nếu ứng dụng của bạn nhỏ và cách tiếp cận này sẽ không quan trọng đối với một tuần tự hóa.

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

cài đặt.NullValueHandling = NullValueHandling.Ignore bị chặn trong các câu trả lời khác. Không rõ ràng, có gì mới trong câu trả lời của bạn
Michael Freidgeim
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.