首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有一种方法可以在不使用Json.NET属性的情况下忽略JsonIgnore中的只获取属性?

是否有一种方法可以在不使用Json.NET属性的情况下忽略JsonIgnore中的只获取属性?
EN

Stack Overflow用户
提问于 2013-08-31 01:09:41
回答 4查看 31.8K关注 0票数 57

是否有一种方法可以使用Json.NET序列化程序而不使用JsonIgnore属性来忽略get-only属性?

例如,我有一个具有以下get属性的类:

代码语言:javascript
复制
    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]添加到所有这些类(我还有许多其他类),还是有更好的方法来忽略所有的只获取属性?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-08-31 13:54:12

您可以通过实现自定义IContractResolver并在序列化期间使用它来做到这一点。如果您对DefaultContractResolver进行了子类,这将变得非常容易:

代码语言:javascript
复制
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();
    }
}

下面是一个测试程序,演示如何使用它:

代码语言:javascript
复制
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

代码语言:javascript
复制
{"Id":2,"Name":"Joe Schmoe"}
票数 87
EN

Stack Overflow用户

发布于 2013-08-31 02:22:45

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

代码语言:javascript
复制
[JsonObject(MemberSerialization.OptIn)]
public class MyClass
{
    [JsonProperty]
    public string serializedProp { get; set; }

    public string nonSerializedProp { get; set; }
}

Udate:添加了使用反射的另一种可能性

如果上面的解决方案仍然不是您想要的,您可以使用反射来生成字典对象,然后将其序列化。当然,下面的示例只适用于简单类,因此,如果类包含其他类,则需要添加递归。这至少会给你指明正确的方向。

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

代码语言:javascript
复制
    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;
    }

显示其用途的片段:

代码语言:javascript
复制
SampleClass sampleClass = new SampleClass();
sampleClass.Hotkey = Keys.A;
var toSerialize = ConvertToDictionary(sampleClass);
String resultText = JsonConvert.SerializeObject(toSerialize);
票数 17
EN

Stack Overflow用户

发布于 2015-12-06 00:32:38

您可以使用这样的合同解析器:

代码语言:javascript
复制
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、get属性和使用set方法的所有属性。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18543482

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档