有没有一种方法可以忽略Json.NET中的只读属性而不使用JsonIgnore属性?

有没有一种方法可以忽略使用Json.NET序列化器的JsonIgnore属性,但不使用JsonIgnore属性?

例如,我有一个类与这些get属性:

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

我是否需要添加[JsonIgnore]给他们(我也有很多其他的类),或者有更好的方法来忽略所有的只读属性?

您可以通过实现一个自定义IContractResolver并在序列化过程中使用它。 如果您将DefaultContractResolver子类化,则这变得非常容易:

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

这是一个testing程序,演示如何使用它:

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

这是上面的输出。 请注意,只读属性LowerCaseName不包含在输出中。

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

使用JSON.net的OptIn模式,你只需要装饰你想要序列化的属性。 这不如自动select所有只读属性,但它可以为您节省一些工作。

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

更新:使用reflection增加了另一种可能性

如果上面的解决scheme仍然不是你正在寻找的东西,你可以使用reflection来制作字典对象,然后序列化。 当然下面的例子只适用于简单的类,所以如果你的类包含其他类,你将需要添加recursion。 这至less应该指向正确的方向。

将过滤结果放入字典的子例程:

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

显示其用途的片段:

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

你可以像这样使用合约parsing器:

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

它将排除计算的属性,但包括C#6只有属性和所有属性与一个方法。

Json.net有能力有条件地序列化没有属性或合约parsing器的属性。 如果你不希望你的项目对Json.net有依赖,这是特别有用的。

根据Json.net文档

要有条件地序列化一个属性,添加一个方法,该方法返回与该属性具有相同名称的布尔值,然后将方法名称作为ShouldSerialize的前缀。 该方法的结果决定了属性是否被序列化。 如果方法返回true,那么该属性将被序列化,如果返回false,则该属性将被跳过。