2012-04-16 19 views
139

Tôi có một lớp DTO mà tôi SerializeLàm thế nào để loại trừ tài sản từ Json serialization

Json.Serialize(MyClass) 

Làm thế nào tôi có thể loại trừ một thuộc tính của nó công?

(Nó phải được công khai, như tôi đã sử dụng nó trong mã của tôi ở một nơi khác)

+4

khuôn khổ nào serialization nào bạn sử dụng? –

+29

'IgnoreDataMember'' ScriptIgnore' 'JsonIgnore' tùy thuộc vào serializer bạn sử dụng –

+1

cũng đáng chú ý là thuộc tính [NonSerialized], chỉ áp dụng cho các trường (không phải thuộc tính), nhưng nếu không có tác dụng tương tự như JsonIgnore. – Triynko

Trả lời

99

Bạn có thể đặt thuộc tính ScriptIgnore trên các thành viên không được đăng theo thứ tự. Xem ví dụ lấy từ here:

xem xét như sau (giản thể) trường hợp:

public class User { 
    public int Id { get; set; } 
    public string Name { get; set; } 
    [ScriptIgnore] 
    public bool IsComplete 
    { 
     get { return Id > 0 && !string.IsNullOrEmpty(Name); } 
    } 
} 

Trong trường hợp này, chỉ có Id và các thuộc tính Tên sẽ được tuần tự, do đó kết quả đối tượng JSON sẽ trông như thế này:

{ Id: 3, Name: 'Test User' } 

PS. Đừng quên thêm tham chiếu đến "System.Web.Extensions" để làm việc này

+6

Tôi tìm thấy 'ScriptIgnore' trong không gian tên' System.Web.Script.Serialization'. –

28

Bạn có thể sử dụng [ScriptIgnore]:

public class User 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    [ScriptIgnore] 
    public bool IsComplete 
    { 
     get { return Id > 0 && !string.IsNullOrEmpty(Name); } 
    } 
} 

Reference here

Trong trường hợp này Id và sau đó tên sẽ chỉ được sắp xếp theo thứ tự

+0

URL trong câu trả lời của bạn bị hỏng. Là '[ScriptIgnore]' những gì nên được sử dụng trên tài sản nếu bộ điều khiển của bạn đang sử dụng bộ điều khiển cơ sở MVC 'return Json (...'? – mmcrae

181

Nếu bạn đang sử dụng Json.Net, thuộc tính [JsonIgnore] sẽ đơn giản bỏ qua trường/porperty trong khi tuần tự hóa hoặc deserialising.

public class Car 
{ 
    // included in JSON 
    public string Model { get; set; } 
    public DateTime Year { get; set; } 
    public List<string> Features { get; set; } 

    // ignored 
    [JsonIgnore] 
    public DateTime LastModified { get; set; } 
} 

Hoặc bạn có thể sử dụng thuộc tính DataContract và DataMember để chọn lọc tuần tự/deserialize thuộc tính/trường.

[DataContract] 
public class Computer 
{ 
    // included in JSON 
    [DataMember] 
    public string Name { get; set; } 
    [DataMember] 
    public decimal SalePrice { get; set; } 

    // ignored 
    public string Manufacture { get; set; } 
    public int StockCount { get; set; } 
    public decimal WholeSalePrice { get; set; } 
    public DateTime NextShipmentDate { get; set; } 
} 

Tham khảo http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size để biết thêm chi tiết

+26

Nếu tôi là OP, tôi sẽ thích câu trả lời này hơn giải pháp [ScriptIgnore] đã chọn, chủ yếu là do sự đồng dư của một giải pháp Json nên vấn đề Json. Tại sao lại liên quan đến System.Web.Extensions khi thư viện bạn đang sử dụng cung cấp giải pháp? IMHO tốt nhất tuyệt đối là thuộc tính [IgnoreDataMember], là System.Runtime.Serialization nên tương thích với mỗi serializer nếu bạn muốn trao đổi ra Json. –

+0

'IgnoreDataMember' không hoạt động với bộ nối tiếp' JsonResult' mặc định. – Hendry

+0

NewtonSoft đã giúp tôi hoàn toàn. Nó làm cho json của tôi trông sạch sẽ mà không có bất kỳ thuộc tính lộn xộn được bao gồm từ các mô hình của tôi mà chỉ dành cho phụ trợ. –

8

Nếu bạn không nên quan tâm đến việc phải trang trí mã với thuộc tính như tôi, đặc biệt là khi bạn không thể nói tại thời gian biên dịch những gì sẽ xảy ra ở đây là giải pháp của tôi.

Sử dụng Javascript Serializer

public static class JsonSerializerExtensions 
    { 
     public static string ToJsonString(this object target,bool ignoreNulls = true) 
     { 
      var javaScriptSerializer = new JavaScriptSerializer(); 
      if(ignoreNulls) 
      { 
       javaScriptSerializer.RegisterConverters(new[] { new PropertyExclusionConverter(target.GetType(), true) }); 
      } 
      return javaScriptSerializer.Serialize(target); 
     } 

     public static string ToJsonString(this object target, Dictionary<Type, List<string>> ignore, bool ignoreNulls = true) 
     { 
      var javaScriptSerializer = new JavaScriptSerializer(); 
      foreach (var key in ignore.Keys) 
      { 
       javaScriptSerializer.RegisterConverters(new[] { new PropertyExclusionConverter(key, ignore[key], ignoreNulls) }); 
      } 
      return javaScriptSerializer.Serialize(target); 
     } 
    } 


public class PropertyExclusionConverter : JavaScriptConverter 
    { 
     private readonly List<string> propertiesToIgnore; 
     private readonly Type type; 
     private readonly bool ignoreNulls; 

     public PropertyExclusionConverter(Type type, List<string> propertiesToIgnore, bool ignoreNulls) 
     { 
      this.ignoreNulls = ignoreNulls; 
      this.type = type; 
      this.propertiesToIgnore = propertiesToIgnore ?? new List<string>(); 
     } 

     public PropertyExclusionConverter(Type type, bool ignoreNulls) 
      : this(type, null, ignoreNulls){} 

     public override IEnumerable<Type> SupportedTypes 
     { 
      get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { this.type })); } 
     } 

     public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) 
     { 
      var result = new Dictionary<string, object>(); 
      if (obj == null) 
      { 
       return result; 
      } 
      var properties = obj.GetType().GetProperties(); 
      foreach (var propertyInfo in properties) 
      { 
       if (!this.propertiesToIgnore.Contains(propertyInfo.Name)) 
       { 
        if(this.ignoreNulls && propertyInfo.GetValue(obj, null) == null) 
        { 
         continue; 
        } 
        result.Add(propertyInfo.Name, propertyInfo.GetValue(obj, null)); 
       } 
      } 
      return result; 
     } 

     public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) 
     { 
      throw new NotImplementedException(); //Converter is currently only used for ignoring properties on serialization 
     } 
    } 
+1

Một thay đổi nhỏ trong logic và 'PropertyExclusionConverter' có thể được chuyển thành một' PropertyInclusionConverter'. – Zarepheth

+0

điều này chỉ là tuyệt vời –

+0

Một vấn đề tiềm năng với điều này là nó phải làm việc trùng tên và loại trừ việc lặp đi lặp lại mỗi khi một đối tượng được đăng. Tuy nhiên, khi đã được biên dịch, các thuộc tính của một loại sẽ không thay đổi - bạn nên thực hiện việc tính toán trước, mỗi loại, các tên cần được bao gồm và chỉ sử dụng lại danh sách trên mỗi hàng. Đối với một công việc tuần tự hóa JSON rất lớn, bộ nhớ đệm có thể tạo ra sự khác biệt đáng chú ý trong hiệu suất. – ErikE

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