2013-08-31 30 views
34

Có cách nào để bỏ qua các thuộc tính chỉ sử dụng bộ nối tiếp Json.NET nhưng không sử dụng thuộc tính JsonIgnore?Có cách nào để bỏ qua các thuộc tính chỉ có trong Json.NET mà không sử dụng các thuộc tính JsonIgnore không?

Ví dụ, tôi có một lớp học với những có được thuộc tính:

public Keys Hotkey { get; set; } 

    public Keys KeyCode 
    { 
     get 
     { 
      return Hotkey & Keys.KeyCode; 
     } 
    } 

    public Keys ModifiersKeys 
    { 
     get 
     { 
      return Hotkey & Keys.Modifiers; 
     } 
    } 

    public bool Control 
    { 
     get 
     { 
      return (Hotkey & Keys.Control) == Keys.Control; 
     } 
    } 

    public bool Shift 
    { 
     get 
     { 
      return (Hotkey & Keys.Shift) == Keys.Shift; 
     } 
    } 

    public bool Alt 
    { 
     get 
     { 
      return (Hotkey & Keys.Alt) == Keys.Alt; 
     } 
    } 

    public Modifiers ModifiersEnum 
    { 
     get 
     { 
      Modifiers modifiers = Modifiers.None; 

      if (Alt) modifiers |= Modifiers.Alt; 
      if (Control) modifiers |= Modifiers.Control; 
      if (Shift) modifiers |= Modifiers.Shift; 

      return modifiers; 
     } 
    } 

    public bool IsOnlyModifiers 
    { 
     get 
     { 
      return KeyCode == Keys.ControlKey || KeyCode == Keys.ShiftKey || KeyCode == Keys.Menu; 
     } 
    } 

    public bool IsValidKey 
    { 
     get 
     { 
      return KeyCode != Keys.None && !IsOnlyModifiers; 
     } 
    } 

Tôi có cần phải thêm [JsonIgnore] cho tất cả trong số họ (Tôi cũng có nhiều lớp khác), hoặc có cách tốt hơn để bỏ qua tất cả các thuộc tính chỉ có?

Trả lời

53

Bạn có thể làm điều này bằng cách thực hiện một phong tục IContractResolver và sử dụng rằng trong serialization. Nếu bạn phân lớp các DefaultContractResolver, điều này trở nên rất dễ dàng để làm:

class WritablePropertiesOnlyResolver : DefaultContractResolver 
{ 
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
    { 
     IList<JsonProperty> props = base.CreateProperties(type, memberSerialization); 
     return props.Where(p => p.Writable).ToList(); 
    } 
} 

Đây là một chương trình thử nghiệm chứng minh làm thế nào để sử dụng nó:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using Newtonsoft.Json; 
using Newtonsoft.Json.Serialization; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Widget w = new Widget { Id = 2, Name = "Joe Schmoe" }; 

     JsonSerializerSettings settings = new JsonSerializerSettings 
     { 
      ContractResolver = new WritablePropertiesOnlyResolver() 
     }; 

     string json = JsonConvert.SerializeObject(w, settings); 

     Console.WriteLine(json); 
    } 
} 

class Widget 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string LowerCaseName 
    { 
     get { return (Name != null ? Name.ToLower() : null); } 
    } 
} 

Dưới đây là sản phẩm của các bên trên. Lưu ý rằng thuộc tính chỉ đọc LowerCaseName không được bao gồm trong đầu ra.

{"Id":2,"Name":"Joe Schmoe"} 
+0

chỉ bỏ qua các thuộc tính mà không cần SET? Và vẫn serialize khi có bộ tư nhân như chuỗi công cộng Tên {get; bộ tư nhân; }? –

12

Sử dụng chế độ OptIn của JSON.net và bạn sẽ chỉ cần trang trí các thuộc tính bạn muốn tuần tự hóa. Điều này không tốt bằng cách tự động chọn không tham gia tất cả các thuộc tính chỉ đọc, nhưng nó có thể giúp bạn tiết kiệm một số công việc.

[JsonObject(MemberSerialization.OptIn)] 
public class MyClass 
{ 
    [JsonProperty] 
    public string serializedProp { get; set; } 

    public string nonSerializedProp { get; set; } 
} 

Udate: Thêm một khả năng sử dụng phản ánh

Nếu giải pháp trên vẫn không khá gì bạn đang tìm kiếm, bạn có thể sử dụng phản ánh để làm cho đối tượng từ điển mà sau đó sẽ được đăng. Tất nhiên ví dụ dưới đây sẽ chỉ làm việc cho các lớp đơn giản, vì vậy bạn sẽ cần phải thêm đệ quy nếu các lớp của bạn có chứa các lớp khác. Điều này ít nhất sẽ chỉ cho bạn đi đúng hướng.

Các chương trình con để đưa kết quả lọc vào một cuốn từ điển:

private Dictionary<String, object> ConvertToDictionary(object classToSerialize) 
    { 
     Dictionary<String, object> resultDictionary = new Dictionary<string, object>(); 

     foreach (var propertyInfo in classToSerialize.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) 
     { 
      if (propertyInfo.CanWrite) resultDictionary.Add(propertyInfo.Name, propertyInfo.GetValue(classToSerialize, null)); 
     } 

     return resultDictionary; 
    } 

Một đoạn cho thấy việc sử dụng nó:

SampleClass sampleClass = new SampleClass(); 
sampleClass.Hotkey = Keys.A; 
var toSerialize = ConvertToDictionary(sampleClass); 
String resultText = JsonConvert.SerializeObject(toSerialize); 
7

Bạn có thể sử dụng một trình giải quyết hợp đồng như thế này:

public class ExcludeCalculatedResolver : DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     var property = base.CreateProperty(member, memberSerialization); 
     property.ShouldSerialize = _ => ShouldSerialize(member); 
     return property; 
    } 

    internal static bool ShouldSerialize(MemberInfo memberInfo) 
    { 
     var propertyInfo = memberInfo as PropertyInfo; 
     if (propertyInfo == null) 
     { 
      return false; 
     } 

     if (propertyInfo.SetMethod != null) 
     { 
      return true; 
     } 

     var getMethod = propertyInfo.GetMethod; 
     return Attribute.GetCustomAttribute(getMethod, typeof(CompilerGeneratedAttribute)) != null; 
    } 
} 

Nó sẽ loại trừ thuộc tính nhưng bao gồm C# 6 chỉ nhận được tài sản và tất cả các thuộc tính với một phương pháp quy định.

4

Json.net không có khả năng tuần tự hóa các thuộc tính mà không có thuộc tính hoặc trình giải quyết hợp đồng. Điều này đặc biệt hữu ích nếu bạn không muốn dự án của bạn có sự phụ thuộc vào Json.net.

Theo Json.net documentation

Để có điều kiện serialize một tài sản, thêm một phương thức trả về boolean với cùng tên với tài sản và sau đó tiền tố tên phương pháp với ShouldSerialize.Kết quả của phương thức xác định xem thuộc tính có được tuần tự hóa hay không. Nếu phương thức trả về true thì thuộc tính sẽ được đăng, nếu trả về false thì thuộc tính sẽ bị bỏ qua.

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