2013-08-27 32 views
8

Tôi có một đối tượng chứa một số thuộc tính là Danh sách các chuỗi List<String> hoặc từ điển của chuỗi Dictionary<string,string>. Tôi muốn serialize các đối tượng để json sử dụng Json.net và tôi muốn có số tiền ít nhất của văn bản được tạo ra.Cách làm cho Json.Net bỏ qua việc tuần tự hóa các bộ sưu tập trống

Tôi đang sử dụng DefaultValueHandling và NullValueHandling để đặt giá trị mặc định thành chuỗi và số nguyên. Nhưng làm thế nào tôi có thể xác định DefaultValueHandling để bỏ qua thuộc tính trong đầu ra tuần tự nếu nó được khởi tạo để trống List<String> hoặc Dictionary<string,string>?

Một số lượng mẫu là:

{ 
"Value1": "my value", 
"Value2": 3, 
"List1": [], 
"List2": [] 
} 

Tôi muốn có được một kết quả mà bỏ qua hai danh sách trong ví dụ trên, bởi vì chúng được thiết lập với giá trị mặc định của một danh sách trống.

Bất kỳ trợ giúp sẽ được đánh giá cao

+0

Tôi không nghĩ điều đó là có thể. Tôi chắc chắn nó sẽ không quá khó để bỏ qua các giá trị 'null' nhưng điều đó sẽ yêu cầu bạn thực hiện các thay đổi ở nơi khác để những tham chiếu đó là null thay vì trỏ đến một danh sách trống. – evanmcdonnal

+0

Tôi chắc chắn điều này có thể được thực hiện với một công cụ chuyển đổi tùy chỉnh (bằng cách thực hiện các lớp trừu tượng JsonConverter), Nhưng tôi quá lười biếng bây giờ để cung cấp một mã. – I4V

+0

Tôi tìm thấy bài viết này có chứa một tham chiếu đến IContractResolver. http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx Điều đó có vẻ là một hướng dẫn tốt để tìm cách triển khai điều này. – agarcian

Trả lời

10

tôi đã thực hiện tính năng này trong custom contract resolver khuôn khổ cá nhân của tôi (liên kết đến specific commit trong trường hợp các tập tin sẽ được chuyển sau). Nó sử dụng một số phương thức trợ giúp và bao gồm một số mã không liên quan cho cú pháp tham chiếu tùy chỉnh. Nếu không có họ, mã sẽ là:

public class SkipEmptyContractResolver : DefaultContractResolver 
{ 
    public SkipEmptyContractResolver (bool shareCache = false) : base(shareCache) { } 

    protected override JsonProperty CreateProperty (MemberInfo member, 
      MemberSerialization memberSerialization) 
    { 
     JsonProperty property = base.CreateProperty(member, memberSerialization); 
     bool isDefaultValueIgnored = 
      ((property.DefaultValueHandling ?? DefaultValueHandling.Ignore) 
       & DefaultValueHandling.Ignore) != 0; 
     if (isDefaultValueIgnored 
       && !typeof(string).IsAssignableFrom(property.PropertyType) 
       && typeof(IEnumerable).IsAssignableFrom(property.PropertyType)) { 
      Predicate<object> newShouldSerialize = obj => { 
       var collection = property.ValueProvider.GetValue(obj) as ICollection; 
       return collection == null || collection.Count != 0; 
      }; 
      Predicate<object> oldShouldSerialize = property.ShouldSerialize; 
      property.ShouldSerialize = oldShouldSerialize != null 
       ? o => oldShouldSerialize(o) && newShouldSerialize(o) 
       : newShouldSerialize; 
     } 
     return property; 
    } 
} 

Hợp đồng này giải quyết sẽ bỏ serialization của tất cả các bộ sưu tập trống (tất cả các loại thực hiện ICollection và có Length == 0), trừ khi DefaultValueHandling.Include được quy định cho các tài sản hoặc lĩnh vực này.

+0

Yeap !!! Điều đó thực sự hiệu quả. Cảm ơn. – agarcian

+0

Tôi nghĩ rằng bạn có thể loại bỏ sự cần thiết của 'memberProp' và' memberField' bằng cách thực hiện 'object value = property.ValueProvider.GetValue (obj);'. – Quartermeister

+0

@Quartermeister Cảm ơn bạn đã đề xuất, cập nhật. – Athari

6

Một giải pháp rất đơn giản khác là triển khai phương thức ShouldSerialize* trong loại được sắp xếp theo thứ tự là here.

Đây có thể là cách ưa thích nếu bạn kiểm soát loại đang được đăng và nếu đó không phải là hành vi chung mà bạn muốn giới thiệu.

Các vấn đề liên quan