NewtonSoft JsonContract ondeserializedcallback未被基本类型调用

本文关键字:类型 调用 JsonContract ondeserializedcallback NewtonSoft | 更新日期: 2023-09-27 18:14:13

在DateTime反序列化之后,我想在中心位置做一些事情。所以我想给合约挂起一个回调,但是它们从来没有被调用过。什么好主意吗?

    public class MyContractResolver : DefaultContractResolver
    {
        protected override JsonContract CreateContract(Type objectType)
        {
            var result = base.CreateContract(objectType);
            var primContract = result as JsonPrimitiveContract;
            if (primContract != null && primContract.CreatedType == typeof(DateTime))
            {
                primContract.OnDeserializingCallbacks.Add((o, context) =>
                {
                    var test = o;
                });
                primContract.OnDeserializedCallbacks.Add((o, context) =>
                {
                    var test = o;
                });
            }
            return result;
        }
    }

回调函数被添加但从未被调用。

NewtonSoft JsonContract ondeserializedcallback未被基本类型调用

你是对的-我能够复制这个(演示小提琴)。

更奇怪的是,对于安装了TypeConverter的非基本类型(例如System.Drawing.Color),因此由JsonStringContract处理,调用OnSerializingOnSerialized回调,但不调用相应的反序列化回调。

您可能想要报告一个问题。

同时,你可以子类化IsoDateTimeConverter或其他继承DateTimeConverterBase的转换器,并在那里添加回调:

public class MyContractResolver : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type objectType)
    {
        var result = base.CreateContract(objectType);
        var primContract = result as JsonPrimitiveContract;
        if (primContract != null 
            && (primContract.CreatedType == typeof(DateTime) || primContract.CreatedType == typeof(DateTime?))
            && primContract.Converter == null
           )
        {
            //Console.WriteLine("Adding {0} callbacks for {1}", primContract.ToString(), objectType.ToString());
            var converter = new MyIsoDateTimeConverter();
            converter.OnDeserializingCallbacks.Add((o, context) =>
            {
                Console.WriteLine("Deserializing " + o);
            });
            converter.OnDeserializedCallbacks.Add((o, context) =>
            {
                Console.WriteLine("Deserialized " + o);
            });
            primContract.Converter = converter;
        }
        return result;
    }
}
class MyIsoDateTimeConverter : Newtonsoft.Json.Converters.IsoDateTimeConverter
{
    private List<SerializationCallback> _onDeserializingCallbacks;
    private List<SerializationCallback> _onDeserializedCallbacks;
    public IList<SerializationCallback> OnDeserializingCallbacks
    {
        get
        {
            if (_onDeserializingCallbacks == null)
            {
                Interlocked.CompareExchange(ref _onDeserializingCallbacks, new List<SerializationCallback>(), null);
            }
            return _onDeserializingCallbacks;
        }
    }
    public IList<SerializationCallback> OnDeserializedCallbacks
    {
        get
        {
            if (_onDeserializedCallbacks == null)
            {
                Interlocked.CompareExchange(ref _onDeserializedCallbacks, new List<SerializationCallback>(), null);
            }
            return _onDeserializedCallbacks;
        }
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var value = base.ReadJson(reader, objectType, existingValue, serializer);
        if (value != null && value is DateTime)
        {
            if (_onDeserializingCallbacks != null)
            {
                foreach (var callback in _onDeserializingCallbacks)
                    callback(value, serializer.Context);
            }
            if (_onDeserializedCallbacks != null)
            {
                foreach (var callback in _onDeserializedCallbacks)
                    callback(value, serializer.Context);
            }
        }
        return value;
    }
}   

注意,对于像DateTime这样具有值语义的类型,在对象构造完成之后但在填充之前调用OnDeserializing事件是没有意义的,因为对象在构造完成时已经完全填充了。因此,我在反序列化之后调用了这两个事件。

另外,阅读JSON中的序列化日期以确保IsoDateTimeConverter将满足您的需求。

小提琴例子。