向json.net添加一个自定义属性



JSON.NET附带了[JsonIgnore][JsonProperty]等属性。

我想创建一些自定义的,当串行化运行时运行。[JsonIgnoreSerialize]或[JsonIgnoreDeserialize]

我将如何扩展框架以包括这一点?

您可以编写类似的自定义合同解析程序

public class MyContractResolver<T> : Newtonsoft.Json.Serialization.DefaultContractResolver 
                                        where T : Attribute
{
    Type _AttributeToIgnore = null;
    public MyContractResolver()
    {
        _AttributeToIgnore = typeof(T);
    }
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var list =  type.GetProperties()
                    .Where(x => !x.GetCustomAttributes().Any(a => a.GetType() == _AttributeToIgnore))
                    .Select(p => new JsonProperty()
                    {
                        PropertyName = p.Name,
                        PropertyType = p.PropertyType,
                        Readable = true,
                        Writable = true,
                        ValueProvider = base.CreateMemberValueProvider(p)
                    }).ToList();
        return list;
    }
}

您可以像一样在序列化/反序列化中使用它

var json = JsonConvert.SerializeObject(
            obj, 
            new JsonSerializerSettings() {
                ContractResolver = new MyContractResolver<JsonIgnoreSerialize>()
            });
var obj = JsonConvert.DeserializeObject<SomeType>(
            json, 
            new JsonSerializerSettings() {
                ContractResolver = new MyContractResolver<JsonIgnoreDeserialize>()
            });

由于您的目标是忽略序列化而不是反序列化的属性,因此可以使用ContractResolver

请注意,下面的类正是这样做的,并且是基于CamelCasePropertyNamesContractResolver的,以确保它序列化为大小写为骆驼形的Json字段。如果您不希望这样,您可以让它从DefaultContractResolver继承。

此外,我自己的例子是基于字符串的名称,但您可以很容易地检查属性是否由自定义属性装饰,而不是比较属性名称。

public class CamelCaseIgnoringPropertyJsonResolver<T> : CamelCasePropertyNamesContractResolver
{        
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        // list the properties to ignore
        var propertiesToIgnore =  type.GetProperties()
                .Where(x => x.GetCustomAttributes().OfType<T>().Any());
        // Build the properties list
        var properties = base.CreateProperties(type, memberSerialization);
        // only serialize properties that are not ignored
        properties = properties
            .Where(p => propertiesToIgnore.All(info => info.Name != p.UnderlyingName))
            .ToList();
        return properties;
    }
}

然后,您可以按如下方式使用它:

    static private string SerializeMyObject(object myObject)
    {
        var settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCaseIgnoringPropertyJsonResolver<JsonIgnoreSerializeAttribute>()
        };
        var json = JsonConvert.SerializeObject(myObject, settings);
        return json;
    }

最后,自定义属性可以是任何类型,但要与示例相匹配:

internal class JsonIgnoreSerializeAttribute : Attribute
{
}

该方法经过测试,也适用于嵌套对象。

不确定这是否是新的,但我建议使用直接处理成员信息的方法GetSerializableMembers。这样,就可以避免与JsonProperty打交道。

public class MyJsonContractResolver : DefaultContractResolver
{
  protected override List<MemberInfo> GetSerializableMembers(Type objectType)
  {
    return base.GetSerializableMembers(objectType)
      .Where(mi => mi.GetCustomAttribute<JsonIgnoreSerializeAttribute>() != null)
      .ToList();
  }
}

相关内容

  • 没有找到相关文章

最新更新