Json.net向每个包含特定类型的类添加属性 [英] Json.net Add property to every class containing of a certain type

查看:80
本文介绍了Json.net向每个包含特定类型的类添加属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为DateTime类型的每个属性添加一个属性到json.

I want to add a property to my json for every property of type DateTime.

我有一个自定义转换器,并且对CreateProperties有覆盖(请参见下文).调试时,返回的属性列表将保存新值,但是当json到达浏览器时,它不包含新属性

I have a custom converter and have an override on CreateProperties (see below). When debugging the returned list of properties holds the new values but by the time the json reaches the browser it does not contain the new properties

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var properties = base.CreateProperties(type, memberSerialization);

        foreach(var prop in base.CreateProperties(type, memberSerialization))
        {
            if(prop != null
                && (prop.PropertyType == typeof(DateTime) || prop.PropertyType == typeof(DateTime?)))
            {
                properties.Add(new JsonProperty() {
                    PropertyName = String.Format("{0}$$type", prop.PropertyName),
                    PropertyType = typeof(String)
                });
            }
        }
        return properties;
    }

首先想到的是,新的Json属性随后将被清除,因为它们无效.可能是因为它们没有值,但是我看不到在此处设置值的方法.

The first thing that comes to mind is that the new Json properties are being wiped off afterwards because they are invalid. Possibly because they have no value, however I can see no way to set the value here.

任何想法都将受到欢迎

推荐答案

您正试图通过 JsonProperty .至少必须初始化

You are trying to add a synthetic read-only property to your serialized JSON via a custom contract resolver. Your problem is that you are not fully initializing the required values of JsonProperty. At the minimum you must initialize

  • PropertyType and PropertyName. You are already doing this.
  • Readable to true and Writable to false.
  • ValueProvider to some appropriate custom implementation of IValueProvider that returns the value you want to see in the JSON for the object being serialized.

此外,建议初始化:

以下操作执行此操作,添加值为"DateTime"的固定字符串属性:

The following does this, adding a fixed string property with the value "DateTime":

public class AddDateTypeFlagContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var properties = base.CreateProperties(type, memberSerialization);
        for (int i = 0, n = properties.Count; i < n; i++)
        {
            var prop = properties[i];
            if (prop.PropertyType == typeof(DateTime) || prop.PropertyType == typeof(DateTime?))
            {
                var name = string.Format("{0}$$type", prop.PropertyName);
                var newProp = new JsonProperty
                {
                    DeclaringType = type,
                    PropertyName = name,
                    UnderlyingName = name,
                    PropertyType = typeof(string),
                    ValueProvider = new FixedValueProvider("DateTime"), // Replace with yout desired string value.
                    AttributeProvider = NoAttributeProvider.Instance,
                    Readable = true,
                    Writable = false,
                    // Ensure PreserveReferencesHandling and TypeNameHandling do not apply to the synthetic property.
                    ItemIsReference = false, 
                    TypeNameHandling = TypeNameHandling.None,
                };
                properties.Add(newProp);
            }
        }

        return properties;
    }
}

public class FixedValueProvider : IValueProvider
{
    readonly object value;

    public FixedValueProvider(object value)
    {
        this.value = value;
    }

    #region IValueProvider Members

    public object GetValue(object target) { return value; }

    public void SetValue(object target, object value)
    {
        throw new NotImplementedException("SetValue not implemented for fixed properties; set JsonProperty.Writable = false.");
    }

    #endregion
}

class NoAttributeProvider : IAttributeProvider
{
    static NoAttributeProvider() { instance = new NoAttributeProvider(); }

    static readonly NoAttributeProvider instance;

    public static NoAttributeProvider Instance { get { return instance; } }

    public IList<Attribute> GetAttributes(Type attributeType, bool inherit) { return new Attribute[0]; }

    public IList<Attribute> GetAttributes(bool inherit) { return new Attribute[0]; }
}

然后,给出以下示例类型:

Then, given the following example type:

public class Example
{
    public string NotADate { get; set; }
    public DateTime ADate { get; set; }
    public DateTime? AnotherDate { get; set; }
}

将生成以下JSON:

{
  "NotADate": "a value",
  "ADate": "2017-04-23T14:25:43.511-04:00",
  "AnotherDate": "2017-04-23T14:25:43.511-04:00",
  "ADate$$type": "DateTime",
  "AnotherDate$$type": "DateTime"
}

它也是基于其他一些属性来创建合成属性.例如,以下代码为模型中的每个DateTime属性添加一个Date属性:

It is also to create a synthetic property based on some other property. For instance, the following adds a Date property for every DateTime property in the model:

public class AddDateFromDateTimeContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var properties = base.CreateProperties(type, memberSerialization);
        for (int i = 0, n = properties.Count; i < n; i++)
        {
            var prop = properties[i];
            if (prop.PropertyType == typeof(DateTime) || prop.PropertyType == typeof(DateTime?))
            {
                var name = string.Format("{0}$$date", prop.PropertyName);
                var newProp = new JsonProperty
                {
                    DeclaringType = type,
                    PropertyName = name,
                    UnderlyingName = name,
                    PropertyType = prop.PropertyType,
                    ValueProvider = new DateTimeToDateValueProvider(prop.ValueProvider),
                    AttributeProvider = NoAttributeProvider.Instance,
                    Readable = true,
                    Writable = false,
                    // Ensure PreserveReferencesHandling and TypeNameHandling do not apply to the synthetic property.
                    ItemIsReference = false,
                    TypeNameHandling = TypeNameHandling.None,
                };
                properties.Add(newProp);
            }
        }

        return properties;
    }
}

public class DateTimeToDateValueProvider : ValueProviderDecorator
{
    public DateTimeToDateValueProvider(IValueProvider baseProvider) : base(baseProvider) { }

    public override object GetValue(object target)
    {
        var baseValue = base.GetValue(target);
        if (baseValue is DateTime)
        {
            return ((DateTime)baseValue).Date;
        }
        return baseValue;
    }

    public override void SetValue(object target, object value)
    {
        throw new NotImplementedException();
    }
}

public abstract class ValueProviderDecorator : IValueProvider
{
    readonly IValueProvider baseProvider;

    public ValueProviderDecorator(IValueProvider baseProvider)
    {
        if (baseProvider == null)
            throw new ArgumentNullException();
        this.baseProvider = baseProvider;
    }

    public virtual object GetValue(object target) { return baseProvider.GetValue(target); }

    public virtual void SetValue(object target, object value) { baseProvider.SetValue(target, value); }
}

请注意,值提供程序是通过将原始属性的值提供程序包装在装饰器中创建的,该装饰器将其值转换为所需的结果.还要注意,JsonProperty.PropertyType设置为要返回的预期类型.使用此合同解析器,会从Example类型生成以下JSON:

Notice that the value provider is created by wrapping the value provider of the original property in a decorator that transforms its value to the required result. Notice also that JsonProperty.PropertyType is set to the expected type to be returned. Using this contract resolver, the following JSON is generated from the Example type:

{
  "NotADate": "a value",
  "ADate": "2017-04-23T14:25:43.511-04:00",
  "AnotherDate": "2017-04-23T14:25:43.511-04:00",
  "ADate$$date": "2017-04-23T00:00:00-04:00",
  "AnotherDate$$date": "2017-04-23T00:00:00-04:00"
}

示例小提琴,展示了两个合同解析器.

Sample fiddle demonstrating both contract resolvers.

这篇关于Json.net向每个包含特定类型的类添加属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆