C# Json自定义对象集合反序列化器

C# Json自定义对象集合反序列化器,c#,.net,json,datetime,serialization,C#,.net,Json,Datetime,Serialization,是否有任何方法可以为对象集合指定自定义反序列化,但仅限于日期 我的意思是: 假设我有一个对象集合——它可以是任何对象,json对它们进行了很好的反序列化。没有日期,一切都好 public List<object> Values { get; set; } 用例: 例如,我有这样的结构: { "Intance": 1, "Values": [ "Ivan", "488-555-1212", "United States", { "S

是否有任何方法可以为对象集合指定自定义反序列化,但仅限于日期

我的意思是:

假设我有一个对象集合——它可以是任何对象,json对它们进行了很好的反序列化。没有日期,一切都好

public List<object> Values { get; set; }
用例:

例如,我有这样的结构:

{
  "Intance": 1,
  "Values": [
    "Ivan",
    "488-555-1212",
    "United States",
    {
      "ShortDesc": "NY",
      "LongDesc": "New York"
    },
    "1985-05-01T00:00:00-05:00"
  ],
  "LastUpdated": "2017-02-06T22:11:34-05:00"
}
比如说-这是生日-

“1985-05-01T00:00:00-05:00”

例如,Web服务时区-东部时间:-5

我的时区是中央时间(美国):-6

在这种情况下,我会得到:1985-04-30——它落后了一天。 这是对的,但我不需要这样的行为,因为今天是我的生日,不应该考虑时区


LastUpdated属性将正确反序列化。

我可以通过添加自定义协定解析程序和自定义属性使其正常工作。所以,当解析器看到该属性时,它会按预期反序列化日期

[AttributeUsage(AttributeTargets.Property)]
public class IgnoreTimeZoneAttribute : Attribute
{
}

public class IgnoreTimeZonePropertyResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);

        foreach (JsonProperty prop in props)
        {
            PropertyInfo pi = type.GetProperty(prop.UnderlyingName);

            if (pi != null && pi.GetCustomAttribute(typeof(IgnoreTimeZoneAttribute), true) != null)
            {
                prop.ValueProvider = new IgnoreTimeZoneValueProvider(pi);
            }
        }

        return props;
    }

    public class IgnoreTimeZoneValueProvider : IValueProvider
    {
        private PropertyInfo _targetProperty;

        public IgnoreTimeZoneValueProvider(PropertyInfo targetProperty)
        {
            this._targetProperty = targetProperty;
        }

        // GetValue is called by Json.Net during serialization.
        public object GetValue(object target)
        {
            return _targetProperty.GetValue(target);
        }

        // SetValue gets called by Json.Net during deserialization.
        // The value parameter has the value/values read from the JSON;
        // target is the object on which to set the value/values without TimeZone info.
        public void SetValue(object target, object value)
        {
            var newValue = value;

            if (typeof(IList).IsAssignableFrom(_targetProperty.PropertyType))
            {
                IList<object> values = value as IList<object>;

                if (values != null)
                {
                    for (int i = 0; i < values.Count - 1; i++)
                    {
                        var curValue = values[i];
                        if (curValue != null && curValue.GetType() == typeof(DateTime))
                        {
                            DateTimeOffset dateTime = new DateTimeOffset((DateTime)curValue);
                            values[i] = dateTime.UtcDateTime.Date;
                        }
                    }
                }
            }

            _targetProperty.SetValue(target, newValue);
        }
    }
}
[AttributeUsage(AttributeTargets.Property)]
公共类IgnoreTimeZoneAttribute:属性
{
}
公共类IgnoreTimeZonePropertyResolver:DefaultContractResolver
{
受保护的重写IList CreateProperties(类型类型,MemberSerialization MemberSerialization)
{
IList props=base.CreateProperties(类型、成员序列化);
foreach(道具中的JsonProperty道具)
{
PropertyInfo pi=type.GetProperty(prop.underyingName);
if(pi!=null&&pi.GetCustomAttribute(typeof(IgnoreTimeZoneAttribute),true)!=null)
{
prop.ValueProvider=新的IgnoreTimeZoneValueProvider(pi);
}
}
返回道具;
}
公共类IgnoreTimeZoneValueProvider:IValueProvider
{
私有财产信息-目标财产;
公共IgnoreTimeZoneValueProvider(PropertyInfo targetProperty)
{
这。_targetProperty=targetProperty;
}
//Json.Net在序列化过程中调用GetValue。
公共对象GetValue(对象目标)
{
返回_targetProperty.GetValue(目标);
}
//SetValue在反序列化期间由Json.Net调用。
//value参数具有从JSON读取的值;
//目标是要在其上设置值/不带时区信息的值的对象。
public void SetValue(对象目标、对象值)
{
var newValue=价值;
if(typeof(IList).IsAssignableFrom(_targetProperty.PropertyType))
{
IList值=作为IList的值;
如果(值!=null)
{
对于(int i=0;i
我会将其序列化为
DateTime
,或者(a)将结果传递给结构/类型的转换器方法/构造函数,或者(b)通过定义自己的比较并在显示时使用格式运算符忽略日期时间的时间部分。为什么要在没有时间的情况下序列化它?例如,它是生日。。。我不需要日期时间。如果您修改您的数据模型以添加?@IvanSalo@Reynevan使用@dbc提供的
[OnDeserialized]
,您可以将日期时间修改为零小时/分钟/秒,或者将其转换为另一个类。您也可以在那里将其从UTC转换为系统时间。它们可能就是你要找的。
[AttributeUsage(AttributeTargets.Property)]
public class IgnoreTimeZoneAttribute : Attribute
{
}

public class IgnoreTimeZonePropertyResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);

        foreach (JsonProperty prop in props)
        {
            PropertyInfo pi = type.GetProperty(prop.UnderlyingName);

            if (pi != null && pi.GetCustomAttribute(typeof(IgnoreTimeZoneAttribute), true) != null)
            {
                prop.ValueProvider = new IgnoreTimeZoneValueProvider(pi);
            }
        }

        return props;
    }

    public class IgnoreTimeZoneValueProvider : IValueProvider
    {
        private PropertyInfo _targetProperty;

        public IgnoreTimeZoneValueProvider(PropertyInfo targetProperty)
        {
            this._targetProperty = targetProperty;
        }

        // GetValue is called by Json.Net during serialization.
        public object GetValue(object target)
        {
            return _targetProperty.GetValue(target);
        }

        // SetValue gets called by Json.Net during deserialization.
        // The value parameter has the value/values read from the JSON;
        // target is the object on which to set the value/values without TimeZone info.
        public void SetValue(object target, object value)
        {
            var newValue = value;

            if (typeof(IList).IsAssignableFrom(_targetProperty.PropertyType))
            {
                IList<object> values = value as IList<object>;

                if (values != null)
                {
                    for (int i = 0; i < values.Count - 1; i++)
                    {
                        var curValue = values[i];
                        if (curValue != null && curValue.GetType() == typeof(DateTime))
                        {
                            DateTimeOffset dateTime = new DateTimeOffset((DateTime)curValue);
                            values[i] = dateTime.UtcDateTime.Date;
                        }
                    }
                }
            }

            _targetProperty.SetValue(target, newValue);
        }
    }
}